应禁用 SSL 验证仅限开发测试,生产环境必须保留;可用 stream_context_create 配置 verify_peer=false 和 verify_peer_name=false 实现 file_get_contents 替代,或 cURL 中设 CURLOPT_SSL_VERIFYPEER=false、CURLOPT_SSL_VERIFYHOST=false 及 CURLOPT_SSLVERSION=CURL_SSLVERSION_TLSv1_2。
直接原因是 cURL 默认启用 SSL 证书校验,而目标服务器用了自签名证书、过期证书,或域名不匹配(比如用 IP 直连 HTTPS 服务),导致 CURLOPT_SSL_VERIFYPEER 和 CURLOPT_SSL_VERIFYHOST 校验失败,报错类似:SSL certificate problem: unable to get local issuer certificate 或 Peer's Certificate issuer is not recognized。
「关闭 SSL 验证」是快速绕过的方法,但仅限开发/测试环境;生产环境必须保留验证,否则会面临中间人攻击风险。
CURLOPT_SSL_VERIFYPEER => false:跳过对服务器证书是否由可信 CA 签发的检查CURLOPT_SSL_VERIFYHOST => false:跳过对证书中 Subject Alternative Name 或 Common Name 是否匹配请求域名的检查false 才能真正“宽松”通过 —— 单设一个仍可能失败(例如证书域名不匹配但签发有效)file_get_contents() 本身不支持直接关 SSL 验证,但可通过 stream_context_create() 配置 HTTP 流上下文实现。这种方式比 cURL 更轻量,适合简单 GET 场景。
$context = stream_context_create([
'http' => [
'method' => 'GET',
'timeout' => 10,
'ignore_errors' => true,
],
'ssl' => [
'verify_peer' => false,
'verify_peer_name' =
> false,
'allow_self_signed' => true,
]
]);
$content = file_get_contents('https://192.168.1.100/api/data.json', false, $context);
注意:verify_peer_name 是 PHP 5.6+ 引入的对应 CURLOPT_SSL_VERIFYHOST 的流选项;allow_self_signed 单独设为 true 不足以绕过校验,必须配合 verify_peer => false。
如果你必须用 cURL(比如要 POST、设 header、处理重定向等),以下是最小化且明确意图的写法:
$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://test.local/endpoint'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // ⚠️ 必须加这行,否则某些旧版 OpenSSL 仍可能报错 curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); $result = curl_exec($ch); curl_close($ch);
遗漏 CURLOPT_SSLVERSION 可能触发 TLS 版本协商失败(尤其在系统 OpenSSL 较老时),表现为超时或空响应;强制指定 TLSv1_2 能提升稳定性和兼容性。
关掉 SSL 验证后,你和远程服务之间的通信完全失去加密信任链保障。攻击者只要在同一局域网或路由节点上劫持流量,就能伪造响应、窃取 token、篡改返回内容 —— 而你的 PHP 代码毫无察觉。
真正该做的不是关验证,而是:
openssl.cafile 或系统 CA 信任库CURLOPT_CAINFO 指定自定义 CA 文件路径(如 /path/to/internal-ca.pem)所谓「宽松」只是临时排障手段,不是长期方案。一旦写进生产代码,后续谁都不敢动它,隐患就埋定了。