cURL error 60 是因 PHP 无法验证 SSL 证书,主因是未正确配置 curl.cainfo 和 openssl.cafile 指向有效的 cacert.pem;需从 curl.haxx.se 下载最新证书,双路径严格一致配置并重启环境。

curl error 60、SSL3_GET_SERVER_CERTIFICATE、unable to get local issuer certificate 这类错误不是 Composer 本身坏了,是 PHP 底层发起 HTTPS 请求时,压根找不到或读不懂可信的 CA 根证书 —— 所有依赖 HTTPS 的操作(下载 packages.json、拉 dist 包、走 GitHub API)都会跪。
确认 PHP 实际加载的证书路径
别猜,让 PHP 自己说它在用哪个文件:
php -r "print_r(openssl_get_cert_locations());"
重点看这两项:
-
default_cert_file:PHP 默认尝试读的路径,为空、不存在、或文件大小为 0,就是病灶 -
ini_cafile:来自php.ini的显式配置,如果和default_cert_file不一致,说明配置没生效,或你改错了php.ini
常见失效路径包括:/etc/ssl/certs/ca-certificates.crt(旧版 Ubuntu)、C:/php/extras/ssl/cacert.pem(XAMPP 自带过期包)、/usr/local/etc/php/cacert.pem(Homebrew PHP 未更新)。
openssl.cafile 和 curl.cainfo 必须同时设且路径完全一致
Composer 同时用到 OpenSSL(如 file_get_contents)和 cURL(默认 HTTP 客户端),两者各认一个配置项:
-
openssl.cafile控制 OpenSSL 层 -
curl.cainfo控制 cURL 层
只配一个?大概率仍有报错。路径写错(漏 .pem、用相对路径、Windows 单反斜杠被当转义符)?照样失败。
正确做法:
- 从 curl.se 官方 下载最新
cacert.pem - 存到稳定绝对路径,例如:
/usr/local/etc/php/cacert.pem或C:/php/cacert.pem - 在
php.ini中写两行,路径一字不差:
openssl.cafile="/usr/local/etc/php/cacert.pem" curl.cainfo="/usr/local/etc/php/cacert.pem"
Windows 路径务必用正斜杠 / 或双反斜杠 \,别用单反斜杠 。
别信 composer config --global cafile
这个命令只影响 Composer 封装的少数 HTTP 驱动(比如 php-http),对默认的 cURL 下载器基本无效。很多人设了还报 curl error 60,就是因为底层 cURL 根本没读这个配置。
临时绕过验证(仅限调试)可选以下方式之一:
- 单次跳过:
composer install --no-secure-http(注意:它不关证书校验,只关仓库协议强制 HTTPS) - 真正禁用证书校验需改环境变量:
COMPOSER_NO_SSL=1 composer install(Linux/macOS)或set COMPOSER_NO_SSL=1 && composer install(Windows CMD)
但这类操作会绕过全部 HTTPS 信任链,中间人攻击风险真实存在 —— 生产环境、CI 流水线、共享服务器上必须避免。
镜像源不能替代证书修复
换阿里云镜像、Laravel China 镜像、甚至 composer config -g disable-tls true,都只是绕开症状。只要 PHP 的 curl.cainfo 和 openssl.cafile 没指向一份有效、完整、路径正确的 cacert.pem,哪怕你把源换成内网地址,只要走 HTTPS,就仍可能在拉 GitHub dist 包、访问 api.github.com 时崩在 curl error 28 或 error 60 上。
最易被忽略的点:系统时间偏差过大也会触发同类错误 —— SSL 证书有明确生效区间,主机时间快 5 分钟或慢 2 小时,都可能导致“证书尚未生效”或“证书已过期”的假象。先 date 看一眼,再排查证书。


















