php内置服务器完全不支持https,仅处理http/1.1明文协议;实现本地https必须通过caddy或nginx等反向代理,无法在php -s上直接启用tls。

PHP内置服务器根本不支持HTTPS
直接说结论:php -S 启动的内置开发服务器**完全不处理TLS/SSL**,它只实现HTTP/1.1明文协议。你看到的任何“用内置服务器跑HTTPS”的尝试,本质上都是在绕过它——要么加反向代理(如Nginx、Caddy),要么改用其他工具。硬要在php -S上套HTTPS,只会遇到Connection refused或浏览器直接报ERR_SSL_PROTOCOL_ERROR。
用Caddy快速代理PHP内置服务器实现HTTPS
Caddy是目前最省心的本地HTTPS方案:自动申请并续期Let’s Encrypt证书,配置极简,且原生支持HTTP→HTTPS重定向。它不替代php -S,而是监听https://localhost:443,把请求转发给http://localhost:8000(你的PHP服务)。
操作步骤:
- 安装Caddy(macOS用
brew install caddy;Windows下载二进制,Linux见官网) - 启动PHP服务:
php -S localhost:8000 router.php - 新建
Caddyfile,内容为:localhost<br>{<br> reverse_proxy http://localhost:8000<br>} - 运行
caddy run(首次会自动获取本地信任证书,浏览器可能提示“不安全”,点“高级→继续访问”即可)
注意:localhost域名在现代浏览器中已被强制要求走HTTPS,Caddy对它有特殊支持;换成test.local之类需额外配hosts和证书信任步骤。
用OpenSSL手动生成自签名证书+nginx代理(适合调试混合协议场景)
当你要测HTTP/2、HSTS头、或需要更细粒度控制证书参数(比如加SAN扩展)时,Caddy的自动证书不够用。这时推荐用OpenSSL生成证书 + Nginx代理:
- 生成私钥和证书:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/CN=localhost" - Nginx配置片段:
server {<br> listen 443 ssl;<br> server_name localhost;<br> ssl_certificate cert.pem;<br> ssl_certificate_key key.pem;<br> location / {<br> proxy_pass http://127.0.0.1:8000;<br> proxy_set_header Host $host;<br> proxy_set_header X-Real-IP $remote_addr;<br> }<br>} - 确保Nginx已启用
ssl模块(nginx -V 2>&1 | grep -o with-http_ssl_module)
常见坑:cert.pem必须包含完整证书链(单文件即可),否则Chrome会报NET::ERR_CERT_AUTHORITY_INVALID;Mac用户需将cert.pem拖入钥匙串并设为“始终信任”。
为什么不用Apache或自己写HTTPS服务器?
Apache配置复杂、启动慢,本地开发纯属杀鸡用牛刀;而用ext/openssl在PHP里手写HTTPS服务器不仅工作量大,还容易出安全漏洞(比如没禁用SSLv3、没设强密码套件)。更重要的是:php -S本身不暴露socket层,无法注入TLS逻辑——它的底层是libevent封装的HTTP parser,没留SSL钩子。
真正要验证HTTPS相关行为(如$_SERVER['HTTPS'] === 'on'、重定向逻辑、证书校验失败响应),唯一可靠方式是让真实TLS终止点(Caddy/Nginx)出现在请求链路上。别试图“骗过”PHP内置服务器。
最容易被忽略的一点:浏览器缓存HTTP重定向(301),如果你先访问过http://localhost,再启HTTPS,可能一直跳不过去——清空浏览器缓存或换隐身窗口测试。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











