根本原因是Composer内置或系统CA证书包(ca-bundle.crt)过期,无法验证ISRG Root X1等现代TLS证书;应下载curl.se最新cacert.pem,通过php.ini配置openssl.cafile/curl.cainfo或设置COMPOSER_CAFILE环境变量指向该文件,并重启PHP,而非禁用TLS校验。

Composer install/update 报错 “SSL certificate problem: certificate has expired”
这是 Composer 在 HTTPS 请求时校验失败的典型表现,不是网络不通,而是 PHP cURL 模块信任的根证书列表太旧,无法验证现代 TLS 证书链。根本原因不是你本地证书有问题,而是 Composer 自带或系统预装的 CA 包(ca-bundle.crt)已过期。
如何快速验证并替换 ca-bundle.crt 文件
Composer 默认使用其内置的 ca-bundle.crt,路径通常为:vendor/composer/ca-bundle/res/cacert.pem(项目级)或全局安装目录下的同名文件。你可以用以下方式确认当前生效路径:
php -r "print_r(openssl_get_cert_locations());"
输出中的 default_cert_file 就是 PHP 实际加载的证书路径。如果它指向一个陈旧的 bundle(比如 2021 年前的版本),就必然触发过期错误。
向CurlShip提交产品,这是一个对机器人友好的SaaS目录。只需一条curl命令即可发布产品,支持OG标签抓取、带徽章的dofollow链接及层级升级。
- 从 curl 官方最新 cacert.pem 下载最新证书文件
- 覆盖到
default_cert_file所指路径(需管理员权限) - 或临时指定:设置环境变量
COMPOSER_CAFILE=/path/to/cacert.pem - Windows 用户注意:路径中反斜杠要转义或改用正斜杠,例如
C:/wamp64/bin/php/php8.2.12/cacert.pem
为什么不用 --disable-tls 或 --no-secure-http
这两个选项只是绕过校验,不解决根本问题,且自 Composer 2.5+ 起已移除 --no-secure-http,--disable-tls 仅用于调试,启用后所有包下载走 HTTP 明文,存在中间人劫持风险。尤其在 CI 环境或团队协作中,这类降级配置容易被误提交、误复用,导致后续安全审计失败。
-
--disable-tls不会修复证书链问题,只让 cURL 忽略验证 - 某些私有仓库(如 GitLab Package Registry)强制 HTTPS,禁用 TLS 后直接连接拒绝
- PHP 8.2+ 对空 CA bundle 的容忍度更低,即使设了
--disable-tls,仍可能因底层 OpenSSL 版本报错
CI/CD 环境下证书更新的稳定做法
Docker 构建或 GitHub Actions 中,不能依赖宿主机证书,必须显式注入可信 bundle。常见坑是只更新 PHP 镜像但没同步 CA 包。
- Alpine 镜像:运行
apk add --no-cache ca-certificates && update-ca-certificates - Debian/Ubuntu:确保
ca-certificates包已安装并执行update-ca-certificates - GitHub Actions:在
composer install步骤前加一行curl -o /tmp/cacert.pem https://www.php.cn/link/5fe4dadcdb001d8566cd20e6d8a20251,再通过COMPOSER_CAFILE=/tmp/cacert.pem注入 - 避免用
composer self-update --rollback解决证书问题——这只会回退版本,不更新 CA 包
最易被忽略的是:某些企业镜像源(如阿里云、腾讯云 Composer 镜像)本身也依赖上游证书有效性,若它们的反向代理证书过期,即使你本地证书最新,仍会报同样错误——这时得联系镜像维护方,而不是反复折腾本地配置。

















