强制https跳转应由nginx通过return 301指令在php前完成;启用trustproxy中间件并配置信任代理网段,确保request::isssl()准确;cookie/session需显式设secure=true,模板与url生成须用https安全方式。

ThinkPHP 本身不处理 HTTPS 协议切换,强制跳转必须由 Web 服务器(Nginx/Apache)完成;在 PHP 层硬做 301 重定向极易引发 ERR_TOO_MANY_REDIRECTS、混合内容或 CLI 崩溃,且 $_SERVER['HTTPS'] 在代理环境下基本不可信。
Nginx 配置 301 跳转才是标准解法
所有流量应在进入 PHP 前就完成协议判断和跳转,这是最安全、最高效、也最解耦的方式。Nginx 原生 return 指令不经过 PHP 解析,无性能损耗,也不受中间件顺序或代理头缺失影响。
- 确保 HTTP server 块监听
80端口,并只写一行:return 301 https://$host$request_uri; - HTTPS server 块监听
443端口,正确配置ssl_certificate和ssl_certificate_key - 若使用 CDN(如 Cloudflare、阿里云 DCDN),必须关闭其「自动 HTTPS 跳转」功能,否则与源站规则叠加导致跳转超限
- 不要用
rewrite+permanent,return 301更直接、更少歧义
TrustProxy 中间件必须启用,否则 isSsl() 永远返回 false
Request::isSsl() 底层依赖 $_SERVER['HTTPS'],而该值在 Nginx + PHP-FPM 或 SLB/CDN 后几乎总是空的。ThinkPHP 不默认信任代理头,必须显式启用 think\middleware\TrustProxy,才能让框架读取 X-Forwarded-Proto。
- 在
app/middleware.php的全局中间件数组中注册:think\middleware\TrustProxy::class - 在
config/app.php中设置:'trust_proxy' => true,并补充'trust_proxies' => ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'](按实际代理网段调整) - 未配此项时,即使 CDN 正确透传了
X-Forwarded-Proto: https,$request->isSsl()仍返回false
中间件跳转要加白名单,不能无差别 redirect
即便你决定在 PHP 层补跳(例如测试环境无法改 Nginx),也绝不能简单判断 !$request->isSsl() 就 301。CLI、AJAX、静态资源、本地开发都会被误伤。
- 排除 CLI:
if (PHP_SAPI === 'cli') { return $next($request); } - 排除 AJAX 请求:
if ($request->isAjax() || $request->header('accept') === 'application/json') { return $next($request); } - 排除本地调试:
if ($request->host() === 'localhost' || $request->host() === '127.0.0.1') { return $next($request); } - 用
$request->url(true)生成跳转地址,它会保留 query、fragment 和编码,比拼$_SERVER变量更可靠
Cookie 和 Session 必须显式设 secure => true
即使全站已强制 HTTPS,ThinkPHP 默认生成的 Cookie 仍不带 Secure 标志。浏览器会在 HTTPS 页面发起请求时,拒绝发送未标记 Secure 的 Cookie,导致登录态丢失、CSRF 失效、反复跳转登录页。
- 修改
config/cookie.php:'secure' => true、'httponly' => true、'samesite' => 'Lax' - 同步修改
config/session.php中的'secure'和'samesite'项 - 若部署在子路径(如
/admin/),还需确认'path'配置匹配,否则 Cookie 不下发 - 模板中避免硬编码
http://链接,前端 JS 用window.location.origin,后端 URL 构建统一加第三个参数:url('index/index', [], true)
真正卡住人的不是代码怎么写,而是搞不清流量路径:Nginx 是否终止 SSL?X-Forwarded-Proto 是否被清洗?代理 IP 是否在 trust_proxies 白名单里?这三个点任意一个漏掉,isSsl() 就不可信,后续所有跳转和安全配置都会失效。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











