您现在的位置:爱折腾>> web>>正文内容

让多说评论框完美支持 HTTPS

我的博客之前一直部署在 Linode,使用Disqus提供的评论服务。Disqus 作为第三方社会化评论的鼻祖,无论功能还是体验,都堪称完美。虽然之前 Disqus 经常加载失败,我也一直在坚守。最近我的 Linode 持续无法访问,几番折腾之后还是换到国内云主机并备案了。借着这次机会,我也把评论从 Disqus 迁移到了国内的多说。多说官方对 HTTPS 的支持并不完美,本文记录我对它的几处改造。

Disqus 和多说都是根据指定 ID 进行评论聚合的第三方系统,将页面上 Disqus 的引用代码换成多说的代码,再按照文档改改参数,评论功能就迁移完成了。数据迁移可以使用前人造好的轮子,例如 Github 上的GavinFoo/DISQUS2DUOSHUO。功能和数据迁移都很简单,这里略过不写。

我的网站配置了CSP 策略,需要把多说用到的域名配置到白名单之中。以下是本站 CSP 全部规则:

content-security-policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: https://*.duoshuo.com; img-src 'self' data: https://*.duoshuo.com; style-src 'self' 'unsafe-inline' https://*.duoshuo.com; connect-src wss://*.duoshuo.com:* https://*.duoshuo.com

多说的种子文件支持 HTTPS,直接把官方地址替换为 HTTPS 即可。但多说有几个地方没考虑周到,需要额外处理:1)用户头像,多说支持多种第三方登录方式,用户头像也支持使用了第三方地址,而这些地址基本都是 HTTP;2)表情,在多说选择表情的浮层中,只有 wordpress 分组中的表情放在多说服务器上并支持 HTTPS,其余分组全部直接使用了 Sina 微博的 HTTP 地址。另外多说评论正文中的表情,也需要替换为 HTTPS 地址。

要解决用户头像问题,可以借用本站 HTTPS 做一个反向代理。我在 Nginx 配置增加了以下内容:

  1. proxy_cache_path    /home/xxx/proxy_cache_path levels=1:2 keys_zone=pnc:300m inactive=30d max_size=10g;  
  2. proxy_temp_path     /home/xxx/proxy_temp_path;  
  3. proxy_cache_key     $host$uri$is_args$args;  
  4.  
  5. server {  
  6.     ... ...  
  7.  
  8.     location ~ ^/proxy/(\w+\.)(bdimg\.com|cdncache\.org|douban\.com|gravatar\.com|qlogo\.cn|sinaimg\.cn)(\/.*)$ {  
  9.         proxy_connect_timeout    10s;  
  10.         proxy_read_timeout       10s;  
  11.  
  12.         proxy_pass               http://$1$2$3;  
  13.  
  14.         proxy_cache              pnc;  
  15.         proxy_cache_valid        200 30d;  
  16.         proxy_cache_lock         on;  
  17.         proxy_cache_lock_timeout 5s;  
  18.         proxy_cache_use_stale    updating error timeout invalid_header http_500 http_502;  
  19.  
  20.         add_header               X-Cache "$upstream_cache_status from cache.ququ";  
  21.  
  22.         expires                  max;  
  23.     }  
  24.  
  25.     location ~ ^/proxy/(.*)$ {  
  26.         rewrite       ^.*$ /static/img/blog/default_avatar.png last;  
  27.     }  
  28.  
  29.     ... ...  
  30. }  

以上配置做了几件事情:1)针对白名单中的 URL 做了反向代理,针对白名单之外的 URL 输出默认头像;2)通过 Nginx 的 proxy_cache 以及 HTTP 的缓存机制,增加访问速度。

有了反向代理之后,可以对多说的embed.js动手术了。我没有找到无侵入的补丁方式,只能粗暴地将官方embed.js托管在本站进行修改。一共修改了以下几处(为了看得更清楚,我加入的代码放在注释里):

  1. avatarUrl: function(e) {  
  2.     /*
  3.     if (e.avatar_url) {  
  4.         e.avatar_url = e.avatar_url.replace(/^http\:\/\//, "https://imququ.com/proxy/");  
  5.     } else {  
  6.         nt.data.default_avatar_url = '/static/img/blog/default_avatar.png';  
  7.     }  
  8.     */ 
  9.  
  10.     return e.avatar_url || nt.data.default_avatar_url  
  11. }  

这处修改,是让多说用户头像走前面配置的 proxy 服务。对于无头像用户,我直接返回了默认头像地址,减少一次 proxy。

  1. addSmilies = function(e, t) {  
  2.     /*
  3.     if(e !== 'WordPress') return;  
  4.     */ 
  5.  
  6.     var s = j.smiliesTooltip;  
  7.     s && s.el.find("ul.ds-smilies-tabs").append("<li><a>" + e + "</a></li>"), j.smilies[e] = t  
  8. }  

这处修改,是让多说不加载 Wordpress 之外的分组表情。由于只剩下一个分组,所以表情浮层样式我也微调了一下,具体效果请看本文评论(实际上,多说评论的样式我改了好多处)。将 Sina 微博表情替换为 proxy 地址,或者是传到支持 HTTPS 的 CDN 也可以,但我觉得没有必要。如果图省事,也可以直接在多说后台关闭评论表情功能。

  1. var t = "",  
  2.     s = e.post,  
  3.     i = e.options,  
  4.     r = s.author;  
  5.  
  6. /*
  7. s.message = s.message.replace(/http:\/\/static\.duoshuo\.com\//g, 'https://static.duoshuo.com/');  
  8. */ 
  9.  
  10. if (t += '<li class="ds-post" data-post-id="' + s.post_id + '">...'){  
  11.     ...  
  12. }  

这处修改,是将评论内容中的表情地址由 HTTP 替换为 HTTPS。

经过以上处理,多说评论所需资源全部会走 HTTPS 了。由于多说代码会更新,本文具有一定的时效性,大家可以参考我的做法自行修改,不要照搬代码。

另外,多说没有 Disqus 那样的新评论通知邮件,我是通过 Github 上的zhengxiaopeng/duoshuo-comment-notification项目实现即时提醒的。

相关文章