Nginx 层用 return 301 https://$host$request_uri; 强制跳转 HTTPS 最稳定;CDN/SLB 需开启强制 HTTPS 并透传 X-Forwarded-Proto;.env 中设 APP_URL=https://yourdomain.com;Session Cookie 必须启用 'secure' => true。

ThinkPHP 6 如何在 Nginx 下自动跳转 HTTPS
不靠框架层做重定向,直接在 Web 服务器层面处理最稳。ThinkPHP 本身不拦截 HTTP/HTTPS 协议判断,$_SERVER['https'] 或 $_SERVER['HTTP_X_FORWARDED_PROTO'] 的值取决于反向代理是否透传,盲目在中间件里写 header('Location: https://...') 容易陷入循环跳转或漏跳。
- Nginx 配置中用
return 301 https://$host$request_uri;,确保只对 80 端口生效 - 如果用了 CDN 或 SLB(如阿里云 CLB),必须开启「强制 HTTPS 转发」并配置
X-Forwarded-Proto头,否则 PHP 拿不到真实协议 - 验证方式:访问
http://yourdomain.com,用浏览器开发者工具看 Network → Headers → Response Status 是否为301 Moved Permanently
ThinkPHP 6 中正确读取当前域名和协议
依赖 request()->domain() 或 url() 生成链接时,若没设对环境变量,会拼出 http:// 链接,尤其在微信、小程序等强 HTTPS 场景下直接报错。
- 务必在
.env文件中显式设置:APP_URL=https://yourdomain.com(不要带结尾斜杠) - 避免使用
request()->scheme() . '://' . request()->host()拼接——当 Nginx 未透传X-Forwarded-Proto时,scheme()返回http,即使实际是 HTTPS - 更安全的写法是统一走
config('app.url'),所有生成 URL 的地方(如url('index/index'))都会自动继承该协议
中间件里做 HTTPS 强制跳转的边界条件
仅当无法修改服务器配置(如共享虚拟主机)时才考虑此方案,且必须加白名单和协议判断,否则生产环境极易挂掉。
- 检查请求头:
if (!in_array(request()->header('x-forwarded-proto', 'http'), ['https', 'HTTPS'])),而非只看$_SERVER['https'] - 排除 CLI 和 API 调试场景:
if (php_sapi_name() !== 'cli' && !request()->isAjax()) - 跳转前确认不是本地开发:
if (!in_array(request()->host(), ['localhost', '127.0.0.1'])) - 示例跳转逻辑:
return redirect()->to(str_replace('http://', 'https://', request()->url()));,别硬编码域名
HTTPS 后 Cookie 和 Session 失效的典型原因
不是 ThinkPHP 的锅,但常被误认为框架问题。本质是 Cookie 缺少 Secure 标志,导致浏览器拒绝在 HTTPS 页面发送 HTTP-only Cookie。
立即学习“PHP免费学习笔记(深入)”;
- 在
config/session.php中确认:'secure' => true(生产环境必须为true) -
'httponly' => true和'samesite' => 'Strict'也建议开启,否则部分新版 Chrome 会丢 Session - 如果用了多级子域名(如
admin.example.com),还要配'domain' => '.example.com',注意开头的点 - 调试技巧:用浏览器 Application → Cookies 查看当前域名下的 Cookie 是否带
Secure标识
X-Forwarded-Proto 给吞了,或者改了又忘了清浏览器 HSTS 缓存。



















