今天,经过无数次折腾,向往已久的域名备案终于下来了。于是迫不及待地将个人博客网站进行 HTTPS 部署迁移,中间遇到一些坑,在此做个记录。
原因
之所以要将网站从 http 迁移到 https,原因有:
- https 更安全,相对于 http 可以较为有效防止中间人攻击,每个项目都希望安全托底。博客虽然没有重要数据,但不失为练兵的好地方。
- 如今 HTTP2 越来越受人关注,它可以提高访问速度,而 HTTP2 的前提就是 HTTPS
步骤
- 安装证书
- nginx 反向代理
- 更改前端连接方式
安装证书
为什么需要证书?这和 HTTPS 协议的设计有关。 HTTPS,指的是 Hypertext Transfer Protocol Secure,另外也也可以称为 HTTP over SSL 或者 HTTP over TLS。通俗一点,HTTPS 通过 Http 协议传输数据,SSL/TLS 加密数据。
它是如何实现加密的呢?
首先,浏览器厂商预先安装了各个 证书颁发机构
的证书,用于对访问网站进行安全验证 然后,个人向 证书颁发机构
申请个人证书,并将证书应用于服务器配置中。 之后浏览器访问服务器,获取公钥,将其与已有的证书列表匹配,决定是否继续。 如果通过,浏览器通过公钥与服务器通信,协商两个非对称私钥,用于各自的数据传输加密,从而建立的加密通道,防止中间人窃听。
如何安装证书? 向证书颁发机构申请证书即可。目前的机构有Symantec、Comodo、GoDaddy 以及 Let’s Certbot。这里我们选择免费的 Let’s Certbot。
在官网上有详细的说明。我的环境是 Linux 16.04 Nginx
,其他的环境可以参照官网说明:
#####安装:
$ sudo apt-get update
$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update
$ sudo apt-get install python-certbot-nginx
复制代码
开始
$ sudo certbot --nginx certonly
复制代码
自动续期
可以参考 这里
根据提示,顺利安装完毕。这里有个前提,就是服务器要有域名,而国内的域名都需要按照工信部要求备案,这也是为什么我需要等待大半个月的原因。
反向代理
证书安装完毕,如果部署在 nginx 中的是静态页面,那么此刻已经顺利部署了 HTTPS 服务。但是更多的应用场景中,我们一方面提供静态服务,如 img、js、css 等等,另一方面我们也需要 REST 服务。 但是此刻,当我们通过 axios 或者 vue-resource 这样的 HTTP client 库来访问 Node.js 服务 API 来获取数据,发现浏览器禁止了该连接。原因是在部署 HTTPS 服务后,整站都要使用 https 来进行数据传递,包括资源的获取,GET/POST
请求等等。
如何解决?我在这走了一些弯路。当时想,因为是访问 Node.js 服务器的 API,我知道 Node.js 是支持 HTTPS 服务的,所以想当然在 Node 中使用 Openssl
来进行自认证。网上有很多类似的教程,但是在浏览器中,对于自认证的证书并不认可。所以这种方法可行但不适用于其他用户访问,更不能应用于生产环境。这里推荐几个工具:
- Postman
- Firefox
第一个是可以发送模拟浏览器发送各种请求,对于测试 API 来说十分方便 第二个之所以在这里推荐是因为我一开始使用 Chrome,但给出的错误提示很模糊,而 Firefox 在 Network 中对于 Request/Response 错误信息会更直白,在这个问题上帮了我很多忙。
正是 Firefox 给出的提示:xxxx 提供了不支持的自签名证书..
,我知道自签名走不通,于是往 Nginx 上考虑了一下,想到 nginx 有反向代理功能,如果说,做一个 api 的反向代理,导航到 node 服务端口,会不会有用呢?于是在网上查找了 Nginx 反向代理的教程,操作如下:
在 /ete/nginx/site-available/default
中:
location /api {
proxy_pass http://localhost:8089;
proxy_buffering on;
}
复制代码
重启 nginx,重启 node 服务。
success!
这样,我们通过反向代理让 REST 服务无需担心证书问题,因为 Nginx 已经做了这一部分工作。
更改前端连接方式
这一部分可选,因为我之前使用的是 vue-resource
,连接使用 this.$http
所以无法对 HTTPS 进行连接,解决该问题,可以:
- 使用 axios,简单优雅处理
最后
整个过程写的比较乱,原因还是自己对 SSL/TLS 的底层协议不熟悉,而且 Nginx 也是新学,反向代理之前只有所耳闻,并没有实际操作过。但不得的说,Nginx 的配置方式比较友好,一看就明白它是什么意思。所以配置起来也不复杂。
接下去会把这部分在深入一点,写一个系列吧。