答案是php底层openssl/curl拒绝验证未被信任的证书链,需正确配置含完整信任链(根ca→中间→叶证书)的pem文件路径并确保权限与顺序正确,而非禁用tls;须区分cli与web环境php.ini、校准系统时间,并优先采用系统级或php级证书信任。

本地私有源 HTTPS 证书不被信任,Composer 直接报 cURL error 60
根本不是 Composer 的错,而是 PHP 底层 OpenSSL/cURL 拒绝验证你私有源的自签名证书链。它要求完整、顺序正确、权限合规的 PEM 文件(含根 CA → 中间 → 叶证书),而不是关 TLS 或硬编码跳过校验。
先确认 PHP 实际加载的证书路径:php -r "print_r(openssl_get_cert_locations());",重点看 default_cert_file 是否存在、可读、非空;常见坑是文件权限为 777(PHP 拒绝加载)或指向已损坏的 bundle。
- Linux/Debian:把你的
your-company-root.crt(PEM 格式,以-----BEGIN CERTIFICATE-----开头)复制到/usr/local/share/ca-certificates/,再执行sudo update-ca-certificates - macOS:双击证书 → “钥匙串访问” → 存入“系统”钥匙串 → 右键 → “显示简介” → “信任” → 设为“始终信任”
- Windows:双击安装 → “本地计算机” → 存储位置选“受信任的根证书颁发机构”
只配 php.ini 不生效?可能被 CLI 和 Web Server 加载不同配置
CLI 模式和 Apache/Nginx 加载的 php.ini 往往不是同一个文件。运行 php --ini 查看 CLI 实际加载路径,phpinfo() 查 Web 环境路径,二者必须分别配置。
在对应 php.ini 中添加两行(路径用正斜杠,Windows 也一样):
openssl.cafile="/path/to/your-company-root.crt" curl.cainfo="/path/to/your-company-root.crt"
改完后必须重启:CLI 需新开终端;Apache/Nginx 必须 systemctl restart apache2 或 nginx,reload 不会重读 php.ini。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
CI/容器环境没法改系统证书?用 composer config --global cafile
这是唯一适合 Docker、GitHub Actions 等受限环境的方式。它只影响 composer 命令本身,不影响 file_get_contents 或其他 PHP 组件。
- 确保你的证书文件是纯 PEM 格式、包含完整信任链(根 CA 在最上面)、路径在容器内可访问
- 执行:
composer config --global cafile /certs/your-company-root.crt - 注意:
vendor/bin/composer默认忽略全局配置,得加--no-plugins或直接调用全局composer
临时禁用 SSL 验证?仅限开发机,且必须加 options.ssl.verify_peer
生产环境绝对禁止。测试时若需快速绕过,只能在项目级 composer.json 的 repositories 段显式关闭:
"repositories": [
{
"type": "composer",
"url": "https://your-private-repo.com",
"options": {
"ssl": {
"verify_peer": false,
"verify_peer_name": false
}
}
}
]
别用 --no-secure-http 或 config -g secure-http false ——它们会全局降级所有 HTTPS 请求,包括 Packagist 官方源,极大增加中间人劫持风险。
真正难搞的不是加证书,而是证书链顺序不对、叶证书没包含、或者系统时间偏差超过 5 分钟导致 JWT 时间戳校验直接失败——这些都得单独验证,不能靠“试了几个命令就以为好了”。










