# SSL operation failed with code 1：Composer 证书校验失败的修法

> Composer 报 SSL operation failed 或 curl error 60，表示 PHP 无法验证 Packagist 或镜像源的证书。应修好 PHP 的 CA 证书包，不要开 disable-tls。

Source: https://ssl.sh/zh/errors/composer-ssl-operation-failed/
Last updated: 2026-11-10

**Composer 报 `SSL operation failed with code 1 ... certificate verify failed` 的意思是：PHP 连上了 Packagist（或你的私有仓库、镜像源），但无法验证它的证书。** 通常是 PHP 没有配置可用的 CA 证书包，或者杀毒软件、公司代理在拦截 HTTPS，或者私有仓库用了 PHP 不认识的内部 CA。

## 快速修复

多数情况下给 PHP 配好 CA 证书包就能解决。先让 Composer 告诉你它用的是哪个证书包：

```bash
composer diagnose -vvv
php -r 'print_r(openssl_get_cert_locations());'
php --ini
```

如果 Composer 报告的 CA 文件不存在或太旧，就在命令行（CLI）使用的 php.ini 里设置有效的证书包：

```ini
openssl.cafile = "/etc/ssl/certs/ca-certificates.crt"
curl.cainfo = "/etc/ssl/certs/ca-certificates.crt"
```

Windows 上从 curl.se 下载 `cacert.pem` 放在 PHP 目录旁边，填它的路径。再运行一次 `composer diagnose`，HTTPS 检查应该就通过了。

## 原因

最常见的原因是 PHP 没有可用的 CA 证书包，其次是杀毒软件或代理在扫描 HTTPS。

### 1. PHP 没有可用的 CA 证书包

Windows 版 PHP、XAMPP、phpStudy 和自行编译的 PHP，`openssl.cafile`、`curl.cainfo` 经常是空的，也没有默认 CA 文件。

- **确认：** `openssl_get_cert_locations()` 指向的路径不存在。
- **修复：** 在 CLI 的 php.ini 里（`php --ini` 会告诉你是哪个）设置这两个参数。Composer 跑在命令行，网站用的 php.ini 改了也没用。

### 2. 杀毒软件或代理在扫描 HTTPS

Composer 排错文档以 Windows 上 Avast 的 HTTPS 扫描为例；公司的 HTTPS 解密代理、上网行为管理效果相同，见 [杀毒软件 HTTPS 扫描](https://ssl.sh/zh/errors/antivirus-https-scanning-ssl-error/) 和 [公司 SSL 解密](https://ssl.sh/zh/errors/corporate-ssl-inspection/)。

- **确认：** `composer diagnose` 能找到有效的 CA 文件但仍然失败；关闭 HTTPS 扫描或换个网络后报错消失。
- **修复：** 在安全软件里把 PHP 或 Composer 排除出 HTTPS 扫描，或者把代理根证书追加到 PHP 使用的证书包里，并向安全软件厂商反馈。

### 3. CA 证书包或 Composer 太旧

旧的 `cacert.pem`、长期不打补丁的系统、旧版 Composer 都可能缺少新的根证书。

- **修复：** 更新系统的 `ca-certificates` 包，重新下载 `cacert.pem`，在证书配置正常后运行 `composer self-update`。

### 4. 私有仓库使用内部 CA

Satis、GitLab、Nexus、Artifactory 等私有 Composer 仓库常用公司内部证书。

- **确认：** 报错的 URL 是内网主机，而 packagist.org 正常。
- **修复：** 把内部根证书追加进证书包，或者只给 Composer 配置：

```bash
composer config --global cafile /etc/ssl/certs/company-bundle.pem
```

如果是服务器没发中间证书，要在服务器上修，可以用 [SSL 检测工具](https://ssl.sh/zh/tools/ssl-checker/)检查。

### 5. 系统时间错误

时间偏差太大，有效证书也会被当成过期证书。开启时间同步即可。

## 各环境修法

宝塔、Linux 发行版、Windows 集成环境和 Docker 的修法一样：让 php.ini 里的 `openssl.cafile` 和 `curl.cainfo` 指向一个有效的 CA 证书包。

**宝塔面板：** 宝塔安装的 Composer 使用对应版本 PHP 的 CLI 配置，php.ini 在 `/www/server/php/<版本号>/etc/php.ini`。在其中设置 `openssl.cafile` 和 `curl.cainfo`，CentOS 系填 `/etc/pki/tls/certs/ca-bundle.crt`，Debian/Ubuntu 系填 `/etc/ssl/certs/ca-certificates.crt`。

**Debian / Ubuntu：** `sudo apt-get install --reinstall ca-certificates`，再确认 `/etc/php/<版本>/cli/php.ini` 没有指向某个过期的自定义证书包。

**CentOS / RHEL / Alibaba Cloud Linux：** 使用 `/etc/pki/tls/certs/ca-bundle.crt`，私有根证书通过 `update-ca-trust` 添加。

**Windows / XAMPP / phpStudy / Laragon：** 在 `php --ini` 显示的 php.ini 里把 `openssl.cafile` 和 `curl.cainfo` 指向下载的 `cacert.pem`，并确认启用了 `extension=openssl`。

**Docker：** 镜像里安装 `ca-certificates`，在 `composer install` 之前复制私有根证书。CI 里安装失败时，第一步先跑 `composer diagnose`。

**业务代码里遇到同样的问题：** 见 [PHP cURL error 60](https://ssl.sh/zh/errors/php-curl-error-60/)。

## 不要这样做

关闭或削弱证书校验后，下载的软件包可能被篡改，所以不要用下面的做法。

- **`composer config -g disable-tls true`。** Composer 文档称其为安全风险，所有下载都会退回明文 HTTP。
- **为了用 `http://` 镜像而设置 `composer config -g secure-http false`。** 国内一些旧教程这样写，它允许在不认证的情况下下载你要执行的代码。
- **在自定义 stream context 或 Composer 插件里关闭 `verify_peer`。** 关掉的正是防止软件包被篡改的那道检查。
- **从非官方渠道下载 `cacert.pem`。** 只用 curl.se 发布的文件或系统包管理器提供的证书包。
