必须在Nginx层用return 301完成跳转,PHP层硬跳易引发ERR_TOO_MANY_REDIRECTS、混合内容或CLI崩溃;$_SERVER['HTTPS']在代理环境下不可信,需启用TrustProxy中间件并配置可信代理网段,Cookie/Session须显式设secure=true。

必须在 Nginx 层用 return 301 完成跳转,PHP 层硬跳极易引发 ERR_TOO_MANY_REDIRECTS、混合内容或 CLI 崩溃;$_SERVER['HTTPS'] 在 Nginx + PHP-FPM 或 CDN 后基本不可信,不能直接依赖。
Nginx 80 端口 server 块必须只写 return 301
这是最安全、最解耦、性能最高的方式——请求根本不会进入 PHP,无中间件顺序、无代理头缺失风险。
- 新建一个独立监听 80 的
server块,仅含三行:listen 80、server_name example.com www.example.com、return 301 https://$host$request_uri; - 严禁在这个块里写
root、index或任何location,否则可能触发 PHP 解析,导致跳转失效或循环 - 若使用 CDN(如 Cloudflare、阿里云 DCDN),务必关闭其「自动 HTTPS 跳转」功能,否则与源站规则叠加,
max_redirects超限 -
return 301比rewrite ... permanent更直接,无正则解析开销,也避免 PATH_INFO 丢失
TrustProxy 中间件必须启用且配对可信网段
$request->isSsl() 在代理后永远返回 false,除非你显式告诉 ThinkPHP:哪些 IP 是可信代理,可以信任它们传来的 X-Forwarded-Proto 头。
- 在
app/middleware.php全局中间件数组**最开头**注册:think\middleware\TrustProxy::class - 在
config/app.php中设置:'trust_proxy' => true,并按实际填写'trust_proxies' => ['127.0.0.1', '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'] - 若用阿里云 SLB 或腾讯云 CLB,确认控制台已开启「传递客户端真实协议」;Nginx 反代时需加:
proxy_set_header X-Forwarded-Proto $scheme; - 未配此项时,哪怕 CDN 正确透传了
X-Forwarded-Proto: https,$request->isSsl()仍为false
Cookie 和 Session 必须显式设 secure=true
即使全站已强制 HTTPS,ThinkPHP 默认生成的 Cookie 仍不带 Secure 标志。浏览器会在 HTTPS 页面拒绝发送这些 Cookie,直接导致登录态丢失、CSRF token 不匹配。
立即学习“PHP免费学习笔记(深入)”;
- 修改
config/cookie.php:'secure' => true、'httponly' => true、'samesite' => 'Lax' - 同步修改
config/session.php:'secure' => true、'samesite' => 'Lax' - 若部署在子目录(如
/admin/),还需补上'path' => '/admin/',否则 Cookie 不下发 - 多级子域名(如
admin.example.com)要设'domain' => '.example.com',注意开头带点
中间件跳转必须加白名单,不能无差别 redirect
即便你决定在 PHP 层补跳(例如测试环境无法改 Nginx),也绝不能只写 if (!$request->isSsl()) { redirect(...) } —— CLI、AJAX、本地调试都会被误伤。
- 排除 CLI:
if (PHP_SAPI === 'cli') { return $next($request); } - 排除 AJAX 或 JSON 接口:
if ($request->isAjax() || $request->header('accept') === 'application/json') { return $next($request); } - 排除本地开发:
if (in_array($request->host(), ['localhost', '127.0.0.1'])) { return $next($request); } - 跳转地址必须用
$request->url(true)生成,它保留 query、fragment 和编码;拼$_SERVER变量在容器或代理后极不可靠
真正容易被忽略的是信任代理网段的精度——CDN 回源 IP 若不在 trust_proxies 列表中,X-Forwarded-Proto 会被框架直接丢弃;而 APP_URL 和模板中 URL 生成逻辑,又依赖这个判断结果。漏配一处,整个 HTTPS 链路就断在中间。



















