根本不是 composer 证书过期,而是 php 加载的 ca 证书文件失效或路径错误——必须用 php -r "print_r(openssl_get_cert_locations());" 确认 default_cert_file 和 ini_cafile 是否有效且一致,再统一配置最新 cacert.pem 到 curl.cainfo 与 openssl.cafile 并重启环境。

根本不是 Composer 证书过期,而是 PHP 加载的 CA 证书文件失效或路径错误——自动化修复必须绕过“猜路径”,直接用 openssl_get_cert_locations() 定位真实加载点,再统一注入最新 cacert.pem。
怎么确认 PHP 实际加载的是哪个证书文件
别改配置前瞎猜。运行这行命令,它会告诉你 PHP 真正在读什么:
php -r "print_r(openssl_get_cert_locations());"
盯死两个字段:default_cert_file(PHP 默认尝试加载的路径)和 ini_cafile(php.ini 中显式配置的路径)。如果前者为空、指向不存在的文件、或对应文件大小为 0,就是根因;如果两者不一致,说明你改的 php.ini 没被加载,或者改错了文件。
常见失效路径包括:
-
C:\php\extras\ssl\curl-ca-bundle.crt(XAMPP 自带,多年未更新) -
/usr/local/etc/php/8.3/openssl.cafile(Homebrew PHP 目录存在但文件没放进去) -
/etc/ssl/certs/ca-certificates.crt(Linux 符号链接失效或内容为空)
如何自动下载并写入最新 cacert.pem(跨平台脚本思路)
手动下载容易漏步骤。推荐用 shell 或 PowerShell 封装成一键操作,核心是三步:下载 → 写入 → 配置。关键点在于路径必须绝对、一致、可读。
Linux/macOS 示例(保存为 fix-composer-certs.sh):
#!/bin/bash CERT_PATH="/usr/local/etc/php/cacert.pem" curl -sSfL https://curl.se/ca/cacert.pem -o "$CERT_PATH" chmod 644 "$CERT_PATH" echo "curl.cainfo=\"$CERT_PATH\"" >> $(php --ini | grep "Loaded Configuration File" | cut -d':' -f2 | tr -d ' ') echo "openssl.cafile=\"$CERT_PATH\"" >> $(php --ini | grep "Loaded Configuration File" | cut -d':' -f2 | tr -d ' ')
Windows PowerShell 示例(需管理员权限):
$certPath = "C:\php\extras\ssl\cacert.pem"
Invoke-WebRequest -Uri "https://curl.se/ca/cacert.pem" -OutFile $certPath
$phpIni = (php --ini | Select-String "Loaded Configuration File").Line.Split(':',2)[1].Trim()
Add-Content $phpIni "curl.cainfo=`"$certPath`""
Add-Content $phpIni "openssl.cafile=`"$certPath`""
注意:curl.cainfo 和 openssl.cafile 必须指向同一文件,且路径中不能含中文、空格、单反斜杠;CLI 下改完需新开终端,Web 环境必须重启 Apache/Nginx/php-fpm。
为什么 secure-http false 不是修复,而是埋雷
执行 composer config -g secure-http false 后,Composer 会允许 HTTP 源,但它不跳过 SSL 校验——只是降级协议。而 packagist.org 及所有主流镜像自 2022 年起已强制 HTTPS,该设置会导致部分命令直接失败,或在某些插件中引发不可预知的连接中断。
真正跳过证书校验的是:composer config -g cafile "" 或清空 php.ini 中 openssl.cafile,这两种操作会让所有 HTTPS 请求裸奔,中间人攻击风险拉满,CI 流水线里一旦误留,等于公开暴露 API Token 和私有包元数据。
临时调试可用但必须显式声明:COMPOSER_NO_SSL=1 composer install,且执行后立刻 unset,避免污染后续命令。
镜像源本身证书链不全时怎么办
如果 php -r "print_r(openssl_get_cert_locations());" 显示证书路径正确、cacert.pem 是 2026 年最新版,但依然报 unable to get local issuer certificate,大概率是镜像服务器配置缺陷:缺少 intermediate CA,新版 OpenSSL 拒绝建立连接。
这不是你能修的,是对方运维问题。优先反馈给镜像方(如阿里云镜像、清华镜像的 GitHub Issue 区);若急需推进,可在单次命令中禁用链验证(仅限本地):
composer install -v --no-ansi --disable-tls
--disable-tls 是 Composer 2.2+ 引入的安全替代,比旧版 --no-ssl 更明确,但仍只应出现在 CI 脚本注释里加 # TODO: remove after mirror fixes chain 的位置。
最常被忽略的一点:证书路径对了,但 PHP 进程没读到——CLI 和 Web 模式可能加载不同 php.ini,php --ini 和 phpinfo() 必须分别验证;容器环境还要确认 cacert.pem 已 COPY 进镜像且权限为 644。











