thinkphp 6 需通过 x-forwarded-proto 头识别 https,因反向代理/cdn 会使 $_server['https'] 失效;应在中间件中检测该头并设 $_server['https']='on',同时配置可信代理校验以确保安全。

ThinkPHP 6 如何正确读取 HTTPS 状态
ThinkPHP 自身不主动探测 HTTPS,它依赖 $_SERVER 中的字段判断协议。很多线上环境(尤其用了 Nginx + 反向代理、CDN、SLB)会导致 $_SERVER['HTTPS'] 为空或为 off,即使实际访问是 HTTPS。这时候 Url::build()、request()->isSsl() 都会误判。
实操建议:
- 优先检查反向代理是否透传了
X-Forwarded-Proto头,Nginx 配置中需有:proxy_set_header X-Forwarded-Proto $scheme; - 在
app/middleware.php中注册一个前置中间件,手动修复请求协议状态:
return function ($request, \Closure $next) {
if ($request->header('x-forwarded-proto') === 'https') {
$_SERVER['HTTPS'] = 'on';
}
return $next($request);
};
- 不要依赖
$_SERVER['SERVER_PORT'] === 443判断——云负载均衡常把 HTTPS 流量解密后以 HTTP(端口 80)转发给后端
如何让 ThinkPHP 自动生成 HTTPS 链接
Url::build() 默认按当前请求协议生成链接,但如果你希望所有生成的 URL 强制走 HTTPS(比如 SEO 或混合内容警告),不能只改模板里写死 https://,而要统一干预 URL 生成逻辑。
实操建议:
- 在
config/app.php中设置:'url_domain_deploy' => true,并确保'url_html_suffix'等配置与部署一致 - 覆盖默认 URL 生成器:在
app/provider.php中绑定自定义think\Url实现类,重写build()方法,在拼接 scheme 时强制用https - 更轻量的做法:在全局公共函数(如
app/common.php)中定义一个封装函数:function https_url($url = '') { return str_replace('http://', 'https://', url($url)); },但注意它不处理相对路径和锚点
Apache/Nginx 下强制跳转 HTTPS 的常见失效原因
直接在 Web 服务器配 301 跳转最可靠,但 ThinkPHP 应用层若启用了 URL 重写(如隐藏 index.php),可能干扰跳转规则执行顺序,导致跳转不生效或循环重定向。
实操建议:
- Apache 用户:把跳转规则放在
.htaccess最顶部,且确保RewriteEngine On在前,跳转规则在重写规则之前:
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
- Nginx 用户:不要在
location /块里写return 301,而应在server块中监听 80 端口单独配置跳转 server:
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
- 避免在 ThinkPHP 的中间件里做跳转(如
if (!request()->isSsl()) { redirect(...) }),这会绕过浏览器 HSTS 缓存,且增加 PHP 执行开销
使用 CDN 后 HTTPS 配置的特殊处理
CDN(如阿里云、Cloudflare)通常终止 HTTPS,再以 HTTP 回源。此时你的服务器永远收不到 HTTPS 请求,request()->isSsl() 永远返回 false,除非你告诉框架“上游已 HTTPS”。
实操建议:
- 确认 CDN 开启了“传递客户端协议头”,并设置回源头为
X-Forwarded-Proto: https - 在 ThinkPHP 的
app/middleware.php中,必须检查该 header 并主动设$_SERVER['HTTPS'] = 'on',否则Cookie::set(..., ['secure' => true])会失效,导致登录态无法携带Secure标志 - 如果 CDN 支持自定义响应头,可加
Strict-Transport-Security: max-age=31536000; includeSubDomains,但 ThinkPHP 不自动注入,得由 Web 服务器或 CDN 控制台配置
真正容易被忽略的是:当多个代理层嵌套(比如 CDN → SLB → Nginx → PHP)时,X-Forwarded-Proto 可能被覆盖或伪造,务必在最外层代理固定写入,并在 PHP 中只信任可信代理 IP 段的 header —— 这部分 ThinkPHP 不提供内置校验,得自己补。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










