Laravel本地开发时URL::to()生成HTTP链接,因默认不识别反向代理的X-Forwarded-Proto头且APP_URL配置为HTTP;需配置可信代理、设置HEADER_X_FORWARDED_PROTO、更新APP_URL/ASSET_URL为HTTPS并清缓存。

为什么 Laravel 本地开发时 URL::to() 生成的是 http 链接
因为 Laravel 默认不感知反向代理或负载均衡器传来的 HTTPS 状态,APP_URL 配置项又写死为 http://,导致所有辅助函数(如 url()、route()、asset())都拼出非加密链接。即使 Nginx/Apache 已正确配置 SSL,Laravel 应用层仍“不知道”当前是 HTTPS。
解决核心:让 Laravel 信任代理传递的 X-Forwarded-Proto 头,并在运行时动态识别协议。
- 确保 Web 服务器(Nginx/Apache)在转发请求给 PHP-FPM 时,设置了
X-Forwarded-Proto: https - 在
AppServiceProvider::boot()中调用Illuminate\Http\Request::setTrustedProxies(),指定可信代理 IP(如['127.0.0.1', 'localhost'])和头字段 - 必须同时设置
Request::setTrustedProxies()的第二个参数为Request::HEADER_X_FORWARDED_PROTO,否则协议不会被识别
Laravel 强制跳转 HTTPS 的三种可靠方式
不能只靠中间件做 301 跳转——静态资源(CSS/JS)、重定向响应头、甚至部分 API 请求可能绕过中间件逻辑,导致混合内容(Mixed Content)警告。
-
Nginx 层最稳:在 server 块中用
return 301 https://$host$request_uri;,所有请求在到达 PHP 前就被重定向,无例外 -
Apache 层次之:启用
mod_rewrite,在.htaccess或虚拟主机配置中加RewriteCond %{HTTPS} off+RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] -
PHP 中间件仅作兜底:适用于无法修改 Web 服务器配置的共享主机环境;但需注意:中间件对
public/下的静态文件无效,且某些 CLI 命令(如php artisan storage:link)可能误触发
APP_URL 和 ASSET_URL 必须设为 HTTPS 协议
这两个环境变量直接影响 Laravel 生成 URL 的基础前缀。如果它们仍是 http:// 开头,即使强制跳转成功,asset('css/app.css') 这类调用仍会输出 HTTP 链接,浏览器直接拦截加载。
-
APP_URL=https://yourdomain.com(不要带尾部斜杠) -
ASSET_URL=https://yourdomain.com(若使用 CDN,可设为https://cdn.yourdomain.com) - 修改后务必清空配置缓存:
php artisan config:clear,否则 .env 变更不生效 - 部署到不同环境时,避免把
APP_URL写死在代码里,始终走.env
Cloudflare / Nginx 反向代理场景下的常见坑
当站点前面有 Cloudflare、CDN 或 Docker Nginx 反向代理时,真实客户端 IP 和协议信息会被掩盖,Laravel 极易误判为 HTTP。
- Cloudflare 用户:必须在
AppServiceProvider中将 Cloudflare 的 IP 段加入可信代理列表(如['173.245.48.0/20', '103.21.244.0/22', ...]),否则X-Forwarded-Proto不被信任 - Nginx 反向代理未透传头:检查 upstream 配置是否包含
proxy_set_header X-Forwarded-Proto $scheme;和proxy_set_header X-Forwarded-For $remote_addr; - 使用
php artisan serve本地调试时,该命令不支持代理头解析,APP_URL必须手动设为 HTTPS 并配合自签名证书,否则无法模拟真实链路
HTTPS 配置不是“开了 SSL 就完事”,Laravel 层、Web 服务器层、CDN 层三者协议标识必须严格对齐,漏掉任意一环都会导致资源加载失败或重定向循环。










