HSTS 必须由 Web 服务器(如 Nginx/Apache)在 HTTPS 响应头中配置,phpEnv 仅管理 PHP 版本与 php.ini,不参与 HTTP 响应;PHP 的 header() 仅在 php -S 环境下有效但不支持 HTTPS,生产环境必须在 Nginx 的 443 server 块中用 add_header ... always 设置,并灰度验证后生效。

HSTS 不是 phpEnv 能配置的,它必须由 Web 服务器(Nginx/Apache)在 HTTPS 响应中发出。phpEnv 是一个 PHP 版本管理工具,只负责切换不同 PHP 解释器,不参与 HTTP 协议层的响应头控制。试图在 phpEnv 配置文件里加 Strict-Transport-Security 没有效果,也不存在所谓“phpEnv 安全协议设置”这个概念。
为什么不能在 phpEnv 中配 HSTS
phpEnv 的作用范围仅限于:
- 修改系统 PATH,让
php命令指向指定版本 - 生成或切换
php.ini配置(影响 PHP 运行时行为,如disable_functions、open_basedir) - 不接触网络层、不监听端口、不发送 HTTP 响应头
而 Strict-Transport-Security 是一个 **HTTP 响应头**,必须由处理 HTTP 请求的 Web 服务器(如 Nginx)或 PHP 应用本身(通过 header())在响应中显式输出。但后者有严重限制——见下一条。
PHP 的 header() 设置 HSTS 仅适用于纯 PHP 服务场景
如果你的 PHP 应用是直接通过 php -S 启动的内置服务器(开发测试用),可以用:
立即学习“PHP免费学习笔记(深入)”;
php -S localhost:8000 -t public/ router.php
并在 router.php 中写:
header('Strict-Transport-Security: max-age=31536000; includeSubDomains; preload');
但注意:
-
php -S不支持 HTTPS,所以这个头在实际生产中会被浏览器忽略(HSTS 只接受 HTTPS 响应) - 真实生产环境几乎都用 Nginx/Apache 反向代理 PHP-FPM,此时 HSTS 必须由 Nginx 配置,否则 PHP-FPM 返回的头可能被 Nginx 覆盖或丢弃
- 即使你在 PHP 中调用
header(),若 Nginx 未启用always参数,遇到 4xx/5xx 错误响应时该头也不会发出
Nginx 中正确配置 HSTS 的关键点
这是你真正该操作的地方(假设你用 phpEnv 搭配 Nginx):
- 只在
listen 443 ssl的server块中添加,绝不在listen 80块中加 - 必须带
always参数:add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; - 确认所有子域名已部署有效 HTTPS 证书,否则开启
includeSubDomains会导致子域完全无法访问 - 首次上线务必先用
max-age=300(5 分钟)灰度验证,等确认跳转、资源加载、API 调用全部正常,再逐步延长
配置后执行 nginx -t && nginx -s reload,再用浏览器开发者工具的 Network 标签检查响应头是否含 Strict-Transport-Security。
最容易被忽略的是:HSTS 生效后,如果某天你临时想回退到 HTTP 测试,浏览器会强制拒绝,且无任何提示——只能等 max-age 过期或手动清除浏览器 HSTS 缓存(Chrome 地址栏输入 chrome://net-internals/#hsts)。这不是配置问题,是协议设计使然。



















