开源评论框 isso 后台无法通过 HTTPS 访问的解决方法

国内的社会化评论框基本上已经都死干净了,国外的比如像 Facebook Comments 或者 Disqus 也是各有各的问题,比如国内根本连不上、Tracker 一大堆影响访客隐私。
这时候自己托管的开源评论框工具就派上用场了,你可以把评论服务托管到自己的服务器上,没有 Tracker,也没有加载速度的问题。我选择了 isso 管理访客评论,因为其架构简单,资源消耗相对较少且无需配置数据库。
但是选择自己搭建这类服务免不了要折腾,部署过程都很简单,但是配置 https 的时候出了很大的问题,整个 isso 对 HTTPS 的支持都有问题,这个问题在管理后台上尤为明显:你没办法通过 https 协议登录后台,会出现 405 报错。花了点时间研究了一些如何解决这一问题,本文记录了我所提供的两种解决方案。

For English version, please checkout this page.

问题复现

为了强制访客使用 https 协议访问网站,大多数网站的做法都是直接把 http 请求 301 到 https 站点上。
这时候就出现问题了,isso 默认你的网站使用 http 协议,所有的资源和链接地址均为 http 开头的,无论你的站使用的是 http 还是 https。如果你在后台登陆,向服务器发送你的登陆密码,它会直接被 POST 到 http 网址上,服务器端检测到 http 地址再把你的请求 301 到 https 网址上,这时候 POST 请求的内容就丢了,因此你会看到 405 Method Not Allowed 的错误。
接下来如果你到审查器里把网址手动改掉并登录,会遇到另外一个问题:JS 和 CSS 加载不出来。造成这一问题的原因同上,无论你的站用的是什么协议 isso 在处理这块时都会强制把网址写成 http,但是在新版本的 Chromium 当中已经把 https 站点当中的 http 请求(又称复合内容)全部屏蔽掉了。也就是说浏览器知道你请求了 http 资源,在向服务器发送请求前就把这个请求拦下来了,服务器根本来不及给你 301 转向,资源自然也就没办法被正常加载。

解决方案

在这里提供两种解决方案,看你用哪个方便。

方案一:CSP

在请求 Header 里面注入一条 CSP 规则:

1
Content-Security-Policy: upgrade-insecure-requests;

浏览器收到这一 header 后会把页面中所有的 http 请求自动升级为 https 请求,如果 https 资源不存在也不会 fallback 直接报错。具体技术细节请参考 MDN 上的这篇文档

如果你服务器上用的是 Nginx 反代的话可以这么写配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server {
listen 443;
server_name [Your domain];

ssl on;
ssl_certificate [Your path];
ssl_certificate_key [Your path];
ssl_trusted_certificate [Your path];

location / {
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://127.0.0.1:[Your port]/;
proxy_redirect off;
add_header Content-Security-Policy "upgrade-insecure-requests" always;
}
}

方案二:修改 isso 配置文件

这个解决方案是我通过 isso 的源代码分析出来的,但是没实际试过所以不能保证一定有效,不过如果你不方便用方案一的话不妨试试并在下面回复告诉我结果(ry

修改 isso 配置文件,在 server 小节添加如下内容:

1
2
[server]
public-endpoint=//example.com

这样会强制改写所有请求资源的 URL,把请求的最前端包含协议和域名的部分改写为 public-endpoint 后面的内容。

请注意,public-endpoint 后面加的不是 http://example.com 或者 https://example.com 而是 //example.com,这样浏览器会根据当前页面所用的协议自动挑选 http 或者 https,这一行为在 RFC2396 当中有定义,所以不需要担心兼容性问题(其实远古级 IE 有点小 bug 但是现在个人开发者已经很少照顾 IE 的兼容性了)。

结语

其实 isso 应当在源代码层面上解决这一问题,我翻了一下源码问题应该是出现在了这里,但是我真的没时间修它,所以在 GitHub 上丢了 issue 就溜了(

如果你也遇到了类似的问题可以试试本文中提到的解决方案,以上就是本文的全部内容,莉莉爱你 ヽ(●´∀`●)ノ ♥。