命令行工具

SSL operation failed with code 1:Composer 证书校验失败的修法

作者: · 最后核实

报错信息SSL operation failed with code 1. OpenSSL Error messages: error:0A000086:SSL routines::certificate verify failed

Composer 报 SSL operation failed with code 1 ... certificate verify failed 的意思是:PHP 连上了 Packagist(或你的私有仓库、镜像源),但无法验证它的证书。 通常是 PHP 没有配置可用的 CA 证书包,或者杀毒软件、公司代理在拦截 HTTPS,或者私有仓库用了 PHP 不认识的内部 CA。

快速修复

多数情况下给 PHP 配好 CA 证书包就能解决。先让 Composer 告诉你它用的是哪个证书包:

composer diagnose -vvv
php -r 'print_r(openssl_get_cert_locations());'
php --ini

如果 Composer 报告的 CA 文件不存在或太旧,就在命令行(CLI)使用的 php.ini 里设置有效的证书包:

openssl.cafile = "/etc/ssl/certs/ca-certificates.crt"
curl.cainfo = "/etc/ssl/certs/ca-certificates.crt"

Windows 上从 curl.se 下载 cacert.pem 放在 PHP 目录旁边,填它的路径。再运行一次 composer diagnose,HTTPS 检查应该就通过了。

原因

最常见的原因是 PHP 没有可用的 CA 证书包,其次是杀毒软件或代理在扫描 HTTPS。

1. PHP 没有可用的 CA 证书包

Windows 版 PHP、XAMPP、phpStudy 和自行编译的 PHP,openssl.cafile、curl.cainfo 经常是空的,也没有默认 CA 文件。

  • 确认: openssl_get_cert_locations() 指向的路径不存在。
  • 修复: 在 CLI 的 php.ini 里(php --ini 会告诉你是哪个)设置这两个参数。Composer 跑在命令行,网站用的 php.ini 改了也没用。

2. 杀毒软件或代理在扫描 HTTPS

Composer 排错文档以 Windows 上 Avast 的 HTTPS 扫描为例;公司的 HTTPS 解密代理、上网行为管理效果相同,见 杀毒软件 HTTPS 扫描 和 公司 SSL 解密。

  • 确认: composer diagnose 能找到有效的 CA 文件但仍然失败;关闭 HTTPS 扫描或换个网络后报错消失。
  • 修复: 在安全软件里把 PHP 或 Composer 排除出 HTTPS 扫描,或者把代理根证书追加到 PHP 使用的证书包里,并向安全软件厂商反馈。

3. CA 证书包或 Composer 太旧

旧的 cacert.pem、长期不打补丁的系统、旧版 Composer 都可能缺少新的根证书。

  • 修复: 更新系统的 ca-certificates 包,重新下载 cacert.pem,在证书配置正常后运行 composer self-update。

4. 私有仓库使用内部 CA

Satis、GitLab、Nexus、Artifactory 等私有 Composer 仓库常用公司内部证书。

  • 确认: 报错的 URL 是内网主机,而 packagist.org 正常。
  • 修复: 把内部根证书追加进证书包,或者只给 Composer 配置:
composer config --global cafile /etc/ssl/certs/company-bundle.pem

如果是服务器没发中间证书,要在服务器上修,可以用 SSL 检测工具检查。

5. 系统时间错误

时间偏差太大,有效证书也会被当成过期证书。开启时间同步即可。

各环境修法

宝塔、Linux 发行版、Windows 集成环境和 Docker 的修法一样:让 php.ini 里的 openssl.cafile 和 curl.cainfo 指向一个有效的 CA 证书包。

宝塔面板: 宝塔安装的 Composer 使用对应版本 PHP 的 CLI 配置,php.ini 在 /www/server/php/<版本号>/etc/php.ini。在其中设置 openssl.cafile 和 curl.cainfo,CentOS 系填 /etc/pki/tls/certs/ca-bundle.crt,Debian/Ubuntu 系填 /etc/ssl/certs/ca-certificates.crt。

Debian / Ubuntu: sudo apt-get install --reinstall ca-certificates,再确认 /etc/php/<版本>/cli/php.ini 没有指向某个过期的自定义证书包。

CentOS / RHEL / Alibaba Cloud Linux: 使用 /etc/pki/tls/certs/ca-bundle.crt,私有根证书通过 update-ca-trust 添加。

Windows / XAMPP / phpStudy / Laragon: 在 php --ini 显示的 php.ini 里把 openssl.cafile 和 curl.cainfo 指向下载的 cacert.pem,并确认启用了 extension=openssl。

Docker: 镜像里安装 ca-certificates,在 composer install 之前复制私有根证书。CI 里安装失败时,第一步先跑 composer diagnose。

业务代码里遇到同样的问题: 见 PHP cURL error 60。

不要这样做

关闭或削弱证书校验后,下载的软件包可能被篡改,所以不要用下面的做法。

  • composer config -g disable-tls true。 Composer 文档称其为安全风险,所有下载都会退回明文 HTTP。
  • 为了用 http:// 镜像而设置 composer config -g secure-http false。 国内一些旧教程这样写,它允许在不认证的情况下下载你要执行的代码。
  • 在自定义 stream context 或 Composer 插件里关闭 verify_peer。 关掉的正是防止软件包被篡改的那道检查。
  • 从非官方渠道下载 cacert.pem。 只用 curl.se 发布的文件或系统包管理器提供的证书包。

常见问题

SSL operation failed 和 curl error 60 有什么区别?

是同一个问题,只是 PHP 走的传输方式不同。装了 curl 扩展时 Composer 用 curl,报 curl error 60;没装时用 PHP 流,报 SSL operation failed with code 1。两者都表示证书链验证失败,所以 openssl.cafile 和 curl.cainfo 最好都设置。

怎么知道 Composer 用的是哪个 CA 文件?

运行 composer diagnose -vvv,输出开头的 Checked CA file ... 或 Checked directory ... 就是 Composer 查找证书包的位置。文件不存在或太旧,就换成从 curl.se 下载的新 cacert.pem,或修改 php.ini 的设置。

能只给 Composer 单独设置 CA 文件吗?

可以:composer config --global cafile /path/to/ca-bundle.pem 会写入 Composer 的全局配置。不过 Composer 文档建议 PHP 5.6 及以上在 php.ini 里设置 openssl.cafile,这样所有 PHP 代码都受益。

换成阿里云 Composer 镜像能解决证书报错吗?

不一定。换镜像解决的是速度问题,如果是本机 PHP 没有 CA 证书包或者公司代理在解密 HTTPS,访问镜像同样会报错。配置镜像时保持 https://:composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/,再按“快速修复”一节修好证书包。

资料来源

  1. Composer: Troubleshooting
  2. Composer: Config (cafile, capath, disable-tls, secure-http)
  3. PHP manual: OpenSSL runtime configuration (openssl.cafile)
  4. PHP manual: cURL runtime configuration (curl.cainfo)
  5. curl: CA certificates extracted from Mozilla