PHP 8.5.5 本身不处理 HTTPS 证书加载或 TLS 握手,依赖 OpenSSL 和 Web 服务器(如 Nginx/Apache)完成证书绑定与加密协商;Web 服务器必须显式监听 443 并配置证书路径,PHP 调用外部 HTTPS 接口时需独立配置 SSL 校验,数据库 SSL 连接须通过 PDO 参数而非 DSN 设置,双向认证应由 Web 服务器层实现。

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false),等于没配。
Web 服务器必须先监听 443 并加载证书
PHP 不会自己读取 /etc/letsencrypt/live/example.com/fullchain.pem 这类路径。这些路径必须由 Web 服务器在配置中显式指定:
- Apache:确认已启用
mod_ssl,并在<virtualhost></virtualhost>块中设置:SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pemSSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem - Nginx:在
server块中写:listen 443 ssl;ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; - 配置后务必验证语法:
sudo nginx -t或sudo apache2ctl configtest,再重启服务
PHP 调用外部 HTTPS 接口时需独立配 SSL 校验
当 PHP 用 curl 或 file_get_contents() 主动请求第三方 HTTPS 接口(比如调用 AI API),Web 服务器的证书配置完全不起作用。此时必须在 PHP 代码里显式控制证书信任链:
- 绝对不要设
CURLOPT_SSL_VERIFYPEER => false—— 这会让中间人篡改 prompt 或窃取api_key - 若对方用自签名证书或私有 CA,把根证书(
.pem格式,不是中间证书)存到服务器本地,例如/etc/ssl/certs/ai-ca.crt - 然后在 cURL 中设置:
curl_setopt($ch, CURLOPT_SSL_CAINFO, '/etc/ssl/certs/ai-ca.crt');curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); - 用
openssl s_client -connect api.example.ai:443 -servername api.example.ai检查返回是否含verify return code: 0 (ok),否则 PHP 会直接失败
ThinkPHP 等框架连 MySQL 的 SSL 不走 DSN,只认 params 数组
很多人把 SSL 参数塞进数据库 DSN(如 mysql:host=xxx;dbname=xxx;ssl_mode=REQUIRED),在 ThinkPHP 6+ 中完全无效。框架只从 config/database.php 的 connections.mysql.params 读取 PDO 原生属性:
- 键名必须是真实常量:
PDO::MYSQL_ATTR_SSL_CA、PDO::MYSQL_ATTR_SSL_CERT、PDO::MYSQL_ATTR_SSL_KEY、PDO::MYSQL_ATTR_SSL_MODE - 值不能是字符串
'PDO::MYSQL_ATTR_SSL_CA',也不能小写,否则被忽略 - 证书路径必须是绝对路径,且 PHP 进程用户(如
www-data)有读权限;SELinux 启用时还需检查上下文 -
PDO::MYSQL_ATTR_SSL_MODE设为1(REQUIRED)适用于内网或自签环境;设为3(VERIFY_IDENTITY)则要求服务端证书 CN 或 SAN 匹配域名,公网云数据库通常需要这个,但自建 MySQL 很少满足
双向认证(mTLS)不是 PHP 实现的,而是 Web 服务器的事
如果你要客户端也提供证书(比如内部系统间强认证),别在 PHP 里折腾 stream_context_create() 加 local_cert 和 passphrase。生产环境应由 Nginx/Apache 完成 TLS 层校验:
立即学习“PHP免费学习笔记(深入)”;
- Nginx 需设:
ssl_verify_client on;+ssl_client_certificate /path/to/ca-bundle.pem; - Apache 需设:
SSLVerifyClient require+SSLCACertificateFile /path/to/ca-bundle.pem - PHP 只能读
$_SERVER['SSL_CLIENT_VERIFY'] === 'SUCCESS'来判断是否通过,不能替代 Web 服务器做握手 - 测试必须用
curl --cert client.pem --key client.key https://api.example.com,浏览器基本不可靠
openssl s_client 看服务端证书链,再用 ls -l 确认 PHP 进程能否读到文件,最后检查 phpinfo() 里 OpenSSL 版本是否 ≥ 1.1.1。



















