答案是PHP底层OpenSSL/cURL未加载可信根证书导致验证失败,需通过php -r "print_r(openssl_get_cert_locations());"定位证书路径,检查文件存在性、完整性、权限(非777),并按系统规范将PEM格式根证书导入信任库或在php.ini中统一配置openssl.cafile与curl.cainfo。

PHP底层没加载到可信根证书
Composer报错cURL error 60: SSL certificate problem: self signed certificate或unable to get local issuer certificate,不是Composer不认证书,而是PHP调用OpenSSL/cURL时找不到或读不了可信根证书文件。它根本没机会验证——连“信任链”都构不起来。
- 先运行
php -r "print_r(openssl_get_cert_locations());",看default_cert_file和ini_cafile指向哪; - 检查该路径是否存在、内容是否为空(常见于Homebrew PHP默认指向一个已损坏的
curl-ca-bundle.crt); - 权限必须是可读但不能是
777(PHP会拒绝加载); - 如果路径指向一个不存在的文件,或文件里只有几行注释,那证书链就断了。
自签名根证书没进系统信任库
你手里有company-root.crt(PEM格式,以-----BEGIN CERTIFICATE-----开头),但只存本地没用——得让它被系统或PHP真正“看见”。不同系统导入方式差异大,别照搬步骤。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- Linux(Debian/Ubuntu):
sudo cp company-root.crt /usr/local/share/ca-certificates/→sudo update-ca-certificates; - CentOS/RHEL:
sudo cat company-root.crt >> /etc/pki/tls/certs/ca-bundle.crt(注意是>>追加,不是覆盖); - macOS:双击安装进“系统”钥匙串 → 右键证书 → “显示简介” → “信任” → 设为“始终信任”;
- Windows:右键安装 → 存储位置选“受信任的根证书颁发机构”;
- 导入后务必重启终端或PHP服务(CLI模式下有时需新开shell才生效)。
Composer单独指定cafile没生效
执行composer config -g cafile /path/to/company-root.crt后仍报错,大概率是因为路径错了、文件不可读,或者你用的是vendor/bin/composer——它默认忽略全局配置。
-
cafile只对composer命令本身生效,不影响file_get_contents()或cURL等其他PHP调用; - 确认路径是绝对路径,且PHP进程有权限读取(比如Docker容器里挂载路径不对就白配);
- 如果项目里
composer.json含"repositories"字段,全局cafile会被跳过; - 更稳妥的做法是:在
php.ini里统一设openssl.cafile和curl.cainfo,两者值必须一致。
镜像源配置掩盖了证书问题
你换了阿里云镜像,composer install不卡了,但不代表证书问题解决了——只是镜像服务器用了公信CA签发的证书,绕过了你的自签名场景。一旦要访问内部私有仓库(如https://repo.internal.company),照样报错。
- 别依赖镜像“治好”SSL错误,它只是躲开了问题;
- 私有仓库域名必须走你导入的根证书,否则
"verify_peer": false这种写法只该出现在测试环境的composer.json里; - 最容易被忽略的是:证书文件里必须只含根CA(不能混叶证书或中间证书),顺序无关,但不能缺;
- 用
openssl x509 -in company-root.crt -text -noout确认它是真正的根CA(Issuer == Subject)。

















