.htaccess中检测HTTPS的多方案代码为何始终返回http?
为什么我的.htaccess协议检测规则始终返回http?
你遇到的问题核心在于mod_rewrite的循环处理机制和规则执行顺序,这也是很多人配置rewrite规则时容易踩的坑。
你的第一条规则是无条件匹配所有请求,直接把protocol设为http——而mod_rewrite默认会循环处理规则,直到没有规则能匹配为止。这意味着哪怕后续规则把protocol改成了https,下一轮循环里第一条规则又会把它改回http,最终你看到的永远是初始设置的http值。
另外,你的规则里重复检测了一些变量(比如%{ENV:HTTPS}和%{HTTPS}),其实%{HTTPS}和%{REQUEST_SCHEME}是Apache内置的核心变量,不需要重复检测环境变量版本;而且REQUEST_SCHEME是Apache 2.4及以上才支持的,如果你用的是2.2版本,这个变量会直接失效。
给你两个修正方案,选哪个都能解决问题:
方案一:调整规则顺序(推荐)
先检测HTTPS场景,满足条件就设置protocol为https并终止规则处理,剩下的情况默认设为http:
# 匹配HTTPS相关场景,设置protocol为https并停止当前规则循环 RewriteCond %{HTTPS} ^on$ [NC,OR] RewriteCond %{REQUEST_SCHEME} ^https$ [NC,OR] RewriteCond %{HTTP:X-Forwarded-Proto} ^https$ [NC] RewriteRule .* - [E=protocol:https,L] # 非HTTPS场景,默认设置为http RewriteRule .* - [E=protocol:http,L]
方案二:给初始规则添加反向条件
保留你原来的逻辑,但给设置http的规则加上反向条件,确保只有非HTTPS请求才会触发它,避免循环覆盖:
# 仅当所有HTTPS条件都不满足时,设置protocol为http RewriteCond %{HTTPS} !^on$ [NC] RewriteCond %{REQUEST_SCHEME} !^https$ [NC] RewriteCond %{HTTP:X-Forwarded-Proto} !^https$ [NC] RewriteRule .* - [E=protocol:http,L] # 匹配HTTPS场景,设置protocol为https RewriteCond %{HTTPS} ^on$ [NC,OR] RewriteCond %{REQUEST_SCHEME} ^https$ [NC,OR] RewriteCond %{HTTP:X-Forwarded-Proto} ^https$ [NC] RewriteRule .* - [E=protocol:https,L]
额外提示:
- 如果你用的是Apache 2.4+,可以把
L换成END,它会完全终止所有mod_rewrite规则的处理,彻底避免循环问题。 - 如果你在反向代理(比如Cloudflare、Nginx)后面,要确保服务器正确传递了
X-Forwarded-Proto头,否则这个检测条件会失效。 - 如果是在PHP中获取这个变量,注意mod_rewrite设置的环境变量会被加上
REDIRECT_前缀(比如$_SERVER['REDIRECT_protocol']),要是想保留原始变量名,可以在规则里写成[E=!protocol:https]。
内容的提问来源于stack exchange,提问作者ElSajko
相关产品推荐
相关产品推荐

