结论:phpenv 的 nginx 配置必须分离 http 跳转与 hsts 处理,80 端口需用独立 server 块配合 return 301(禁用 rewrite),443 端口须在 server 顶层加 add_header ... always;hsts 必须全响应生效、子域 https 可达且证书匹配,preload 前需严格验证三项硬性条件。

直接说结论:phpEnv 的 Nginx 配置必须拆开处理 HTTP 跳转和 HSTS,不能只改一个 server 块;否则跳转不安全、HSTS 不生效、preload 申请会失败。
80 端口必须用 return 301 而非 rewrite 实现跳转
phpEnv 默认可能带 rewrite 规则,但这是隐患:它依赖 $host 或 $http_host,容易被恶意 Host 头注入,跳转到钓鱼域名。正确做法是在独立的 listen 80 server 块中用 return 301:
- 删掉所有
rewrite ^/(.*)$ https://$host$1 permanent;类规则 - 确保该 server 块只监听 80 端口,且
server_name明确列出所有合法域名(如example.com www.example.com) - 使用
return 301 https://$server_name$request_uri;——$server_name是配置里白名单的值,不会被请求头污染 - 加上
underscores_in_headers off;防止非法 header 解析
443 端口必须在 server 块顶层加 add_header + always
HSTS 头必须出现在所有 HTTPS 响应中,包括 404、500、304。很多人把 add_header 写在 location 里(比如只放在 location ~ \.php$ 中),结果静态资源或根路径响应不带 HSTS,导致 preload 审核失败。
- 在
listen 443 ssl的 server 块最外层(即server { ... }内,不在任何location下)添加:add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; -
always参数不可省略,否则 4xx/5xx 响应不发 HSTS 头 - 确认证书覆盖了
server_name中所有域名(含 www 和裸域),否则启用 HSTS 后用户直接打不开站 - 不要在 http 块全局加
add_header,Nginx 的继承规则会导致 80 端口也发 HSTS(无效且报错)
preload 上线前必须验证三个硬性条件
hstspreload.org 拒绝任何“看起来像对”的配置,只认实际响应行为。上线前必须逐条验证:
- 用
curl -I https://example.com确认响应头含Strict-Transport-Security,且max-age=31536000、含includeSubDomains、含preload - 用
curl -I http://example.com确认返回 301,且Location值是https://example.com/...(不是https://$http_host这类可篡改形式) - 访问所有子域(如
api.example.com、cdn.example.com)并确认它们:① 能 HTTPS 直达(非重定向);② 响应头同样含完整 HSTS;③ 证书有效且匹配 - 首次提交前,先用
max-age=300测试 24 小时,再调高——HSTS 一旦生效,浏览器缓存期内无法回退
最容易被忽略的是子域 HTTPS 可达性:preload 要求每个子域都必须能通过 HTTPS 直接响应(状态码 200+,非 301 跳转),且证书不能是自签名或过期。哪怕一个子域漏配,整个预加载申请就会被拒,且后续修正周期极长。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











