Nginx+Let’s Encrypt环境file_get_contents报certificate verify failed错误如何解决
可能成因
- 服务器本地CA根证书包版本过旧:2024年9月30日Let's Encrypt旧的DST Root CA X3交叉签名根证书正式到期,若服务器的ca-certificates包长期未更新,会无法验证使用Let's Encrypt证书的站点的SSL有效性,这也是无配置变更前提下突然报错的最常见原因。
- PHP配置未实际生效:PHP在php-fpm、CLI、Apache模块等不同运行模式下会加载不同的php.ini配置文件,若修改的不是当前运行环境加载的配置,修改不会生效。
- 目标站点SSL证书链配置不完整:你用file_get_contents请求的目标站点部署Let's Encrypt证书时未配置完整的中间证书,导致客户端无法完成证书链溯源验证。
- 全局配置未被file_get_contents读取:部分PHP版本下file_get_contents的stream流默认不会读取php.ini中的openssl.cafile配置,需要单独在请求上下文指定参数才会生效。
解决方案
1. 更新本地CA根证书包
Debian/Ubuntu系统执行以下命令:
sudo apt update && sudo apt install ca-certificates -y sudo update-ca-certificates
CentOS/RHEL系统执行以下命令:
sudo yum update ca-certificates -y sudo update-ca-trust extract
更新完成后重启PHP服务(根据你的运行环境重启php-fpm或Apache),再测试功能是否恢复。
2. 核对配置文件路径
在触发错误的PHP运行环境下输出phpinfo(),搜索Loaded Configuration File字段,确认你之前修改的php.ini路径和该字段显示的路径完全一致,修改配置后必须重启PHP服务才会生效。
3. 代码中显式指定SSL配置
如果上述步骤无效,可以直接在业务代码中指定CA证书路径,不依赖全局配置:
$sslContext = stream_context_create([ 'ssl' => [ 'verify_peer' => true, 'verify_peer_name' => true, 'cafile' => '/etc/ssl/certs/ca-bundle.crt' ] ]); $responseContent = file_get_contents('目标请求URL', false, $sslContext);
若你是遇到外部请求你的站点报该错误,检查Nginx配置中ssl_certificate参数指向的是Let's Encrypt生成的fullchain.pem文件,而非cert.pem,fullchain.pem才包含完整的证书链。
临时测试方案(仅验证问题用,不建议线上使用)
如果需要快速确认是否为证书验证环节导致的问题,可以临时关闭SSL验证:
$sslContext = stream_context_create([ 'ssl' => [ 'verify_peer' => false, 'verify_peer_name' => false ] ]); $responseContent = file_get_contents('目标请求URL', false, $sslContext);
该方案存在严重安全风险,测试完成后必须立即恢复SSL验证。
内容的提问来源于stack exchange,提问作者Yeo Bryan
相关产品推荐
相关产品推荐

