导读

HTTPS 是什么?我们为什么要用到它?
在网站上线之后如何实现 HTTPS 访问,并通过 Rewrite 实现http跳转至https?

4月27日 2:34 更新:附录部分详细解释了 Rewrite 规则,简单说了说正则表达式。

Head Pic:ReVdol!官方海报 (我永远喜欢罗兹!)


1. 前言

1.1. HTTPS 与 SSL 证书

一句话:HTTPS 相当于 HTTP 的加强版。
简单来说,HTTPS 在 HTTP 的基础上加入了 SSL 协议。

  • SSL 证书基于 SSL 协议,文章中如无说明,SSL 均指 SSL 证书。
  1. SSL 是数字证书的一种,由证书、公钥和私钥组成。用户申请访问网站时,服务器会先向用户的浏览器发送证书和公钥,用户的浏览器会验证该证书是否有效,如果无效则会警告用户该网站不安全,并让用户自行决定是否继续访问。
  2. 接着用户的浏览器会生成一份对称秘钥,然后在利用服务器的公钥加密后发送给服务器,服务器用私钥解密后,双方都拥有了相同的对称秘钥了。
  3. 之后的会话期间所有数据均会使用这个对称秘钥来保障数据安全。

HTTPS流程.png

图1.1 SSL证书原理

通过此种方式的会话的安全性远高于不使用 SSL 证书的会话。这也是为什么如今的大多数的网站都纷纷使用了 HTTPS 协议。
说了这么多,那么到底该如何实现 HTTPS 呢?

1.2. 操作环境

在本文所提到的方法基于如下的操作环境:

  • 操作系统: CentOS 7.6.1810 x86_64
  • Apache版本:Apache 2.4.6

理论上适用于 CentOS 7,及 Apache 2 以上的服务器。


2. 检查 Apache 配置

首先找到你的 Apache 目录,例如:/etc/httpd
在服务器的根目录输入vim /etc/httpd/conf/httpd.conf

[[email protected] /]# vim /etc/httpd/conf/httpd.conf

如果你再这个文件中找到了#LoadModule ssl_module modules/mod_ssl.so字段,那么恭喜你,你的 Apache 的模块是完整的,只需要在网上随便找一篇相关的文章进行配置就行。
但是如果你跟我一样, Apache 模块安装的不完全,没有这个字段,则请继续往下阅读。

首先按下 Esc 键退出编辑模式,然后按下 Shift + ; 来输入 :,再输入 q,按下Enter键就可以退出 vim 模式了。
Apache 的 HTTPS 功能依赖于 mod_ssl 模块,但是我们在装 Apache 的时候 由于缺乏前瞻性 没有安装这个模块。
接下来我们安装 mod_ssl 模块:

[[email protected] /]# yum install mod_ssl

安装完成后,我们就可以开始下一步操作了。


3. 获取证书

玩装完 mod_ssl 模块后,服务器现在已经支持 HTTPS 了,然后我们就可以在网址前加上 https:// 访问……了吗?
啊事实上是不可以的,有没有发现一件事 —— 我们还没有 SSL 证书

3.1. 证书价格

其实, https 这个技术其实早就有了,但是为什么现在仍有相当一部分网站没有用 https 协议呢?不是因为不成熟,而是……
GoDaddy SSL证书价格

图3.1.1 GoDaddy SSL证书价格

没想到吧?其实这个价格已经算很便宜了,10k一年甚至更贵的证书都有。
这个价格对于企业来说其实不算什么,但是对于我们来说就是天文数字了。

……抬头看一看,你会发现我的网址前面是有 https 的,哪来的?
这就要提到免费证书了。

3.2. 免费证书

事实上,为了推广 https,市面上已经出现了一大批的免费证书。这些证书就付费证书来说安全性相同(当然和企业级的证书相比还是要差一些),不过都会有各种各样的弊端。
3.2.1 阿里云的免费 SSL 证书

图3.2.1 阿里云的免费 SSL 证书

阿里云能提供免费的 DV SSL 证书,时效一年,不能续期,这就意味着你需要每隔一年就重新申请和配置一遍证书。
3.2.2 又拍云的免费 SSL 证书

图3.2.2 又拍云的免费 SSL 证书

又拍云好一些,能申请时效一年的 DV SSL 证书,同时支持自动续期。

不过不管哪一家的免费证书,都有一个致命问题 —— 只支持单域名。也就是如果你为www.example.com配置了证书,你就不能为bbs.example.com配置证书了。
不过这无伤大雅,毕竟我们做个人博客一般用一个二/三级域名就够了。
简单来说,去申请你喜欢的一家服务商提供的证书就可以了。


4. 安装证书

4.1. 下载证书

在你购买了证书后,就可以将证书下载下来了。
4.1.1 阿里云下载证书.png

图4.1.1 阿里云下载证书界面

其他几家下载证书的方式大同小异,如果实在不知道在哪下载,可以自行查看服务商的帮助页面。
下载好证书后,里面的内容是这样子的:
图4.1.2 下载好的证书内容

图4.1.2 下载好的证书内容

接下来,我们将这三份文件上传到服务器中就可以了:
图4.1.3 上传证书到服务器

图4.1.3 上传证书到服务器

上传到哪里都是随意的,但是你要记住你上传到服务器的哪个位置,例如我的是:/etc/httpd/cert/

[[email protected] ~]# cd ..
[[email protected] /]# cd etc/httpd/cert/
[[email protected] cert]# ls
*******_dreamrill.cn_chain.crt  *******_dreamrill.cn.key  ******_dreamrill.cn_public.crt
检查是否成功上传

到了这一步,已经基本完成了,接下来就是激活服务了。


5. 启动 HTTPS 服务

还记得我们之前安装了一个 mod_ssl 模块吗,现在该它上场了。
我们找到这个模块的配置文件,然后依次找到如下语句:

SSLCertificateFile cert/public.pem
SSLCertificateKeyFile cert/ca.key
SSLCertificateChainFile cert/chain.pem

[[email protected] ~]# cd ..
[[email protected] /]# cd etc/httpd/conf.d/
[[email protected] conf.d]# ls
autoindex.conf  php.conf  README  ssl.conf  userdir.conf  welcome.conf
[[email protected] conf.d]# vim ssl.conf

进入vim后,我们按i进入编辑模式,然后我们分别把这三个语句指向的路径改成我们之前上传的证书的路径:
图5.1 修改路径

图5.1 修改路径

修改完毕后我们按下 Esc 退出编辑模式,再接下来输入 : ,然后输入 wq 就可以保存退出了。

然后,我们确认一下防火墙开启了 https 的访问,如果觉得麻烦,也可以直接关闭防火墙。

[[email protected] ~]# systemctl status firewalld.service
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: active (running) since Fri 2019-04-26 22:00:56 CST; 4s ago
     Docs: man:firewalld(1)
 Main PID: 22244 (firewalld)
   CGroup: /system.slice/firewalld.service
           └─22244 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid

如果显示了 active(running)则代表了防火墙现在是启动的。
我们通过如下命令来为防火墙添加 https 的白名单:

firewall-cmd --permanent --add-service=https

如果需要关闭防火墙(不建议),则输入:

systemctl stop firewalld.service

最后,我们重启一下httpd服务:

systemctl restart httpd

现在,试试在你的网址前面加上 https:// ,你会发现,你已经可以通过 https 来访问网站啦!


附加: 让 http 跳转到 https

在做完如上猛如虎的操作后,我们还差最后的临门一脚 —— 让 http 跳转到 https 。
事实上,即便现在我们已经可以通过 https 来访问网站了,但是你可能会发现,使用 http 也能访问你的网站。
这就代表了可能仍有会话是通过 http 协议的,不仅数据不安全,同时也不利于搜索引擎收录你的网站。
这时候我们可以通过 Apache 的 Rewrite 功能来实现跳转。
找到网站根目录下的 .htaccess 文件,如果没有就创建一个 ——
图 附加1 .htaccess 文件

图附加1 .htaccess 文件

然后在这个文件里添加如下语句:

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
</IfModule>

第一句 RewriteEngine on 直译为启动 Rewrite 引擎。
第二句表示 Rewrite 生效的位置,如果你感觉不好理解,直接写 RewriteBase / 即可,意思为 Rewrite 对服务器的所有目录生效。
第三句的 RewriteCond 表示规则生效的条件,这里的条件是“如果访问服务器的端口不是443”,这里也可以写成 RewriteCond %{SERVER_PORT} 80
第四句为整个 Rewrite 生效的部分,主要是正则表达式。不知道正则表达式的也没关系,我就简单说说:

  1. ^ 为匹配字符串的开始
  2. $ 为匹配字符串的结束
  3. . 为匹配换行符以外的所有字符,* 为重复0次或更多次。
  4. 那么就很明显了, ^.*$ 即为匹配用户请求访问的地址。
  5. 然后 Rewrite 到 一个新链接,%{SERVER_NAME} 会输出 Apache 的配置文件 httpd.conf 中的 ServerName 值,例如 kira.cool。 %{REQUEST_URI} 会输出域名之后的值,以本篇文章为例,就是 /note/16-apache-achieve-https-access
  6. 以本篇文章为例,例如我访问了网址 http://kira.cool/note/16-apache-achieve-https-access。 因为 http 用的是 80 端口,满足了 RewriteCond 的判断,然后调用了 RewriteRule 规则,将网址重写为 https:// + kira.cool + /note/16-apache-achieve-https-access

以上说法有些不严谨,但是无甚大碍,能理解就行。最后重启 httpd 服务就大功告成了。

至此,本文的全部内容就结束了,感谢你的阅读,欢迎继续阅读本站的其他文章。