答案是系统时间偏差超2分钟或php的ca证书路径失效;先运行date和php -r "print_r(openssl_get_cert_locations());"定位问题,再校准时间、更新cacert.pem并同步配置curl.cainfo与openssl.cafile。

Composer 报 SSL 证书验证失败,90% 不是网络问题,而是本地时间偏差或 PHP 的 CA 证书路径失效——先查 date 和 php -r "print_r(openssl_get_cert_locations());",比换镜像源更关键。
系统时间偏差超2分钟直接触发 certificate has expired
OpenSSL 校验 HTTPS 证书时,严格比对证书的 notBefore 和 notAfter 字段与本地系统时间。偏差哪怕快 3 分钟或慢 2 分钟,就会报 SSL certificate problem: certificate has expired,和证书本身是否过期无关。
- 先运行
date,再打开 time.is 对比;误差 > 120 秒就锁定为时间问题 - macOS:执行
sudo sntp -s time.apple.com(Catalina+)或sudo ntpdate -u time.apple.com(旧版) - Linux:启用 NTP 同步
sudo timedatectl set-ntp true,再sudo systemctl restart systemd-timesyncd - Windows:管理员运行
w32tm /resync;若失败,先配置源w32tm /config /syncfromflags:manual /manualpeerlist:"time.nist.gov" - 容器环境必须修宿主机时间——Alpine 需额外安装
openntpd或挂载/etc/timezone
PHP 的 CA 证书路径指向空、错或过期文件
报 unable to get local issuer certificate 或 certificate verify failed,大概率是 openssl.cafile 或 curl.cainfo 指向了一个不存在、权限不足或停更于 2021 年前的证书文件(比如含已吊销的 DST Root CA X3)。
- 运行
php -r "print_r(openssl_get_cert_locations());",重点看ini_cafile和default_cert_file的值 - 若为空或路径无效(如
/private/etc/ssl/cert.pem在 macOS 上根本不存在),需手动指定 - Homebrew 安装 OpenSSL@3 的常见路径:
/opt/homebrew/etc/openssl@3/cert.pem(Apple Silicon)或/usr/local/etc/openssl@3/cert.pem(Intel) - 下载最新 CA 包:
curl -sS https://curl.se/ca/cacert.pem -o /path/to/cacert.pem(别用浏览器另存,会带 HTML) - 在
php.ini中补两行:curl.cainfo = "/path/to/cacert.pem"和openssl.cafile = "/path/to/cacert.pem" - CLI 模式需新开终端;Apache 或 PHP-FPM 必须完整重启(
sudo apachectl restart或sudo systemctl restart php-fpm)
镜像源配置错误导致 fallback 到 packagist.org
即使时间准、证书新,composer install 仍卡在 Loading composer repositories 或报 Could not resolve host: packagist.org,说明 Composer 没走你设的镜像,而是退回到被污染的官方源。
- 检查是否生效:
composer config -g repo.packagist输出必须是完整 JSON,例如{"type": "composer", "url": "https://mirrors.aliyun.com/composer/"} - 三要素缺一不可:
repo.packagist(单数)、type值显式为"composer"、URL 末尾带/(https://mirrors.aliyun.com/composer/✅,https://mirrors.aliyun.com/composer❌) - 项目级
composer.json里只要出现"repositories"字段(哪怕空数组[]),全局配置立即失效 - 临时清掉:
composer config --unset repositories - 验证真实请求地址:
composer install -vvv 2>&1 | grep Downloading | head -n 1,第一行 URL 才是实际发出的请求
权限与安全边界常被忽略的细节
最麻烦的不是报错本身,而是排查路径跑偏:把时间不准当成网络问题,把证书路径错当成镜像失效,把 secure-http false 当成万能解药——它只禁用 HTTPS 强制要求,并不跳过证书校验,而国内主流镜像(阿里云、腾讯云)已全量拒绝 HTTP 请求。
-
composer config -g disable-tls true会让所有请求降级为 HTTP,结果是400 Bad Request或连接重置,不是“修复”,是误配 -
--no-secure-http同理,作用域窄但依然无效于当前主流镜像策略 - 真正绕过证书校验得动 PHP 层:
PHP_SSL_NO_VERIFY=1 composer install(仅限单次调试) - 用
sudo composer install生成的vendor/目录属主为root,后续普通用户操作会报Permission denied,不是证书问题,是权限混乱 - Docker 构建中,
FROM php:8.5-cli等基础镜像默认不启用 NTP,且未预装 CA 证书包,必须显式RUN apt-get update && apt-get install -y ca-certificates(Debian)或apk add ca-certificates(Alpine)











