curl 默认不校验 SSL 证书,必须同时设置 CURLOPT_SSL_VERIFYPEER => true 和 CURLOPT_SSL_VERIFYHOST => 2,并正确配置 CURLOPT_CAINFO 绝对路径指向可信 CA 证书(如 cacert.pem),否则校验失效或报错。

curl 默认不校验 SSL 证书,必须显式开启
PHP 的 curl_exec() 默认跳过证书验证,哪怕对方证书已过期、域名不匹配或由未知 CA 签发,请求照样成功——这不是“兼容性好”,是默认不安全。关键开关是 CURLOPT_SSL_VERIFYPEER 和 CURLOPT_SSL_VERIFYHOST,二者必须同时设为 true 才算真正启用校验。
-
CURLOPT_SSL_VERIFYPEER => true:验证证书是否由可信 CA 签发(依赖系统或自定义 CA 证书) -
CURLOPT_SSL_VERIFYHOST => 2:严格验证证书中Subject Alternative Name或CN是否匹配目标域名(2是必须,1已被弃用且不生效) - 若只开
VERIFYPEER而不开VERIFYHOST,证书可能签发给example.com,但你访问api.example.com也会通过
CA 证书路径没配对,CURLOPT_CAINFO 就会失效
Linux/macOS 通常自带系统级 CA 证书(如 /etc/ssl/certs/ca-certificates.crt),但 Windows 和部分 Docker 镜像没有。PHP 不会自动读取系统证书库,必须手动指定 CURLOPT_CAINFO 或 CURLOPT_CAPATH,否则 CURLOPT_SSL_VERIFYPEER => true 会直接报错 SSL certificate problem: unable to get local issuer certificate。
- 推荐用 Mozilla 维护的
cacert.pem(从 curl.se 下载),存到项目目录如./certs/cacert.pem - 设置时路径必须是绝对路径:
curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . '/certs/cacert.pem'); - 别用相对路径或
dirname(__FILE__)拼接后没 realpath(),容易因工作目录变化导致找不到文件
自签名证书或私有 CA 场景下,不能只靠 CURLOPT_SSL_VERIFYPEER
对接内部服务(如测试环境用自签名证书、企业私有 CA)时,强行开启 VERIFYPEER 会失败。此时不能关掉校验,而是把自签名证书或私有 CA 根证书加进信任链。
- 把自签名证书(
server.crt)或私有 CA 根证书(internal-ca.crt)合并进你的cacert.pem,或单独指定:curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . '/certs/internal-ca.crt'); - 绝不要用
CURLOPT_SSL_VERIFYPEER => false来“快速解决”,这等于裸奔;临时调试可加日志记录跳过原因,但生产环境禁止 - 如果服务端用了客户端证书双向认证,还需配置
CURLOPT_SSLCERT和CURLOPT_SSLKEY,但那是另一层验证,和证书校验本身无关
PHP 8.1+ 的 stream_context 方式也需等效校验
不用 cURL?用 file_get_contents() + stream_context_create() 也会遇到同样问题。它的 SSL 校验开关在上下文选项里,不是默认开启的。
- 必须显式设置:
'verify_peer' => true、'verify_peer_name' => true、'cafile' => __DIR__ . '/certs/cacert.pem' - 漏掉
verify_peer_name(对应 cURL 的VERIFYHOST)会导致域名校验失效 - PHP 8.1 开始,
allow_self_signed默认为false,但仅控制是否允许自签名证书,不替代 CA 校验逻辑
最常被忽略的是:开了 VERIFYPEER 却没配 CAINFO,或配了但路径不对,结果 curl 返回 false 且 curl_error() 提示模糊——这时候先检查 curl_getinfo($ch, CURLINFO_HTTP_CODE) 是不是 0,再看 curl_errno() 是不是 60 或 51,就能快速定位是证书链问题还是域名不匹配。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











