根本原因是 openssl 无法验证证书链,需配置 openssl.cafile 指向完整 pem 格式 ca bundle 绝对路径,确保权限正确并重启 php-fpm;该配置全局生效,优于单次 curl 的 curlopt_cainfo。

PHP cURL 请求 HTTPS 报错 “cURL error 60” 或 “SSL certificate problem: unable to get local issuer certificate”,根本原因通常是 openssl 无法验证证书链——它只拿到了域名证书,却找不到对应的中间证书(Intermediate CA)来向上追溯到可信根。直接在 php.ini 中设置 openssl.cafile 是最稳定、影响全局的修复方式,但路径和权限稍有差池就无效。
为什么 openssl.cafile 比 CURLOPT_CAINFO 更值得优先配置
这个配置项作用于 OpenSSL 底层,所有 PHP 扩展(如 cURL、stream_context_create、PDO_PGSQL 的 SSL 连接等)都会继承它;而 CURLOPT_CAINFO 只影响单次 cURL 请求,漏设一处就可能报错。尤其在 ThinkPHP、Laravel 等框架中,HTTP 客户端底层仍走 OpenSSL,统一配 openssl.cafile 能一劳永逸。
- 必须是 PEM 格式完整 CA bundle,不能是单个证书或 DER 文件
- 路径必须为绝对路径,Windows 下注意反斜杠要双写或用正斜杠(
/etc/ssl/certs/cacert.pem✅,C:\php\cacert.pem❌) - Web 进程用户(如 www-data、nginx、apache)必须有该文件的读取权限,常见坑是上传后 chmod 丢了
- 修改后必须重启 PHP-FPM(不只是 Web 服务),否则不生效
openssl.cafile 的正确写法与验证方式
打开 php.ini,找到这一行(通常在 [openssl] 段落里):
openssl.cafile=/etc/ssl/certs/cacert.pem
确认路径真实存在且内容可读:
- 下载最新
cacert.pem:从 https://www.php.cn/link/5fe4dadcdb001d8566cd20e6d8a20251 获取(2026 年仍在维护) - Linux 示例:
sudo curl -o /etc/ssl/certs/cacert.pem https://www.php.cn/link/5fe4dadcdb001d8566cd20e6d8a20251 && sudo chmod 644 /etc/ssl/certs/cacert.pem - 验证是否加载成功:
php -r "print_r(openssl_get_cert_locations());",检查输出中default_cert_file是否等于你设置的路径
当 openssl.cafile 不起作用时,先查这三件事
很多“配了没用”其实是被掩盖的低级错误:
-
php.ini不是你实际加载的那个:运行php --ini看 Loaded Configuration File,别改错文件 - CLI 和 Web SAPI 使用不同
php.ini:浏览器访问phpinfo()页面,搜索Loaded Configuration File,和命令行结果对比 - 证书文件本身损坏:用
head -n 5 /etc/ssl/certs/cacert.pem确认开头是-----BEGIN CERTIFICATE-----,且无 BOM 或乱码
宝塔面板用户特别注意:别让面板覆盖你的 openssl.cafile
宝塔升级或重装 PHP 时,会重写 php.ini,把自定义的 openssl.cafile 行删掉。更稳妥的做法是:
- 把
cacert.pem放到宝塔习惯路径,比如/www/server/php/{version}/etc/cacert.pem - 在
php.ini中写成:openssl.cafile=/www/server/php/{version}/etc/cacert.pem - 每次 PHP 版本更新后,进宝塔【软件商店】→ 找到对应 PHP → 【设置】→ 【配置修改】,手动补回这一行
证书链问题从来不是“有没有证书”,而是“能不能连上信任锚点”。openssl.cafile 就是告诉 PHP:“这是你唯一该信的根名单”,一旦路径错、权限缺、文件旧,整个链就断在第一跳。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











