最近建站时有这样一个需求,网站使用了 Cloudflare 的 CDN 加速服务,要实现强制 HTTPS 访问
我用的是 nginx,理论上来说在 80 端口的配置里写好 HTTP 301 或 302 转发就可以了
server {
listen 80;
listen [::]:80;
server_name <domain>;
return 301 https://<domain>$request_uri; # HTTP 301 永久重定向至 HTTPS
# return 302 https://<domain>$request_uri; # HTTP 302 临时重定向也可以,看具体需求选用
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name <domain>;
...
但在实际测试过程中,HTTP 可以跳转到 HTTPS,但 HTTPS 一直出现 ERR_TOO_MANY_REDIRECTS
错误
排查了一通之后,发现锅出在 Cloudflare 上面:如图,在默认情况下,Cloudflare 与源服务器之间的流量通讯是不走 SSL/TLS 加密的,也就是直接走了上面的 80 端口,会被 301/302 回去,如此循环多次之后,浏览器便会报出 ERR_TOO_MANY_REDIRECTS
错误。

所以不能只在 nginx 中使用 301 转发,要在 Cloudflare 的 SSL/TLS 设置页中将 加密模式 修改为 完全;或者直接使用 灵活 模式,只加密浏览器到 Cloudflare 之间的流量,也算是变相实现了强制 HTTPS
那么问题又来了,我的域名不是通过正常的 NS 手段接入 Cloudflare 的,而是通过 Cloudflare Partner 提供的 CNAME 方式接入,Cloudflare Partner 并未提供 SSL/TLS 设置页面,上面的方案也就无法实施
转念一想,后端是可以获取到浏览器访问地址的,我们可以借助后端处理,变相实现伪强制 HTTPS
网站采用了 PHP 作为网站后端,那么也就可以利用 PHP 的 auto_prepend_file
特性,在每一个经过 PHP 处理的页面前插入跳转代码
<?php
# Force SSL redirect
function isSSL() {
return (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") || (isset($_SERVER["HTTP_X_FORWARDED_PROTO"]) && $_SERVER["HTTP_X_FORWARDED_PROTO"] == "https") || ((int) $_SERVER["SERVER_PORT"] == 443);
}
if (!isSSL()) {
header("HTTP/1.1 301 Moved Permanently"); # 若要使用 HTTP 302,删去此行
header("Location: https://" . $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"]);
}
# auto_prepend_file 只能插入一个文件,你也可以在这个文件中写点其他内容
?>
在服务器上随便找个地方,将上面的代码保存成 php 文件,之后在 php.ini 中插入以下配置
auto_prepend_file = "/path/to/file.php" ; 文件的相对/绝对路径
或在 nginx 引入 FastCGI 的部分插入
location ~ [^/]\.php(/|$) {
...
fastcgi_param PHP_VALUE "auto_prepend_file=/path/to/file.php"; # 文件的相对/绝对路径
...
}
.htaccess 则是这么写
php_value auto_prepend_file "/path/to/file.php"
保存,重载配置,测试,正常从 HTTP 跳转到 HTTPS,大功告成
这种实现也有它的缺陷:
- 非全局强制 HTTPS,不走 FastCGI 处理的文件(如 html、png 等)不会自动跳转,不够安全(
不怕性能损耗和 CGI 爆炸导致全站暴毙的话,可以将所有文件都走 FastCGI 处理) - 可能会造成性能损耗,给服务器带来更大的压力
好像没了?
小哥哥msmdown那个的破解好不好分享下
MsmDownloadTool破解不外传