2024-11-11

如何修复 Windows 上的 PHP Curl HTTPS 证书颁发机构问题

成功的 HTTPS 请求涉及 HTTP 客户端验证
服务器根据已知且受信任的根列表提供的 TLS 证书
证书。 PHP Curl 扩展没有什么不同;卷曲
扩展使用 libcurl 发出 HTTPS 请求,而 libcurl 又使用 OpenSSL 等 TLS 库来验证请求。

图片.png

Curl 扩展需要一个包含以下内容的有效文件:所有的
受信任的根证书来完成HTTPS验证,以及PHP
将其公开为 php.ini 文件中的指令。

在 Linux、BSD 和 macOS 上,libcurl 可以默认为系统根目录
证书,但这在 Windows 上是不可能的,因为 Windows 确实
不附带包含所有系统根目录的单个文件
证书。

本文讨论了使用 Curl 扩展成功发出 HTTPS 请求的两种可能方法,以及不采取哪些措施可能导致 HTTPS 请求不安全。

失败原因

$ch = curl_init('https://php.watch');  
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  
curl_exec($ch); // false  

curl_error($ch);
// SSL certificate problem: unable to get local issuer certificate
登录后复制

如果curl_exec调用失败并返回错误响应,并且如果curl_error指示SSL证书问题:无法获取本地颁发者证书错误,这意味着Curl未提供包含根证书的文件,或者无法发现它。

此错误在 Linux、BSD 和 macOS 系统上并不常见,但相当多
Windows上常见,因为没有指定文件获取root
证书,并且 PHP 不在其上提供根证书列表

解决方案是提供一个包含最新根目录的文件
证书,或者理想情况下,让 Curl 解析本地根存储
底层操作系统提供。

使用本机证书颁发机构

在 Curl 7.71 及更高版本上,可以设置 Curl
请求 Curl 使用本机(系统)根证书的选项。
这甚至在 Windows 上也有效,其中 Curl 解析系统根证书
并使用它们。

当 CURLOPT_SSL_OPTIONS 选项设置为 CURLSSLOPT_NATIVE_CA 时
或包含这些位的位掩码,Curl 尝试使用本机
根证书存储,取决于证书的功能和版本
底层 TLS 库。

如果 Curl 扩展是使用 Curl 7.71 或更高版本以及 PHP 8.2 及更高版本构建的,这是建议的修复。

 $ch = curl_init('https://php.watch');
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
   curl_setopt($ch, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA);
    curl_exec($ch);
登录后复制

请注意,上面的代码片段不会检查Curl 版本和 PHP
版本,并假设满足 PHP 和 Curl 版本要求。这
以下是有条件地添加 Curl 选项的示例:

$ch = curl_init('https://php.watch');  
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  
if (defined('CURLSSLOPT_NATIVE_CA')  
  && version_compare(curl_version()['version'], '7.71', '>=')) {  
    curl_setopt($ch, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA);
}  
curl_exec($ch);
登录后复制

下载并维护 cacert.pem 文件

对于在 8.2 之前的 PHP 版本上运行的应用程序(其中 CURLSSLOPT_NATIVE_CA
常量不可用),或者当 Curl 版本低于 7.71 时,
推荐的替代解决方案是下载 Curl 兼容的
根证书文件,并配置 PHP 或 Curl 请求来使用它。

Curl 项目维护着最新的证书列表。请参阅从 Mozilla 提取的 CA 证书。

立即学习PHP免费学习笔记(深入)”;

  1. 下载 cacert.pem 文件

  2. 将文件移动到 PHP 和 Web 服务器可访问的目录。例如,C:/php/cacert.pem。
  3. 编辑 php.ini 文件并修改curl.cainfo 条目以指向 cacert.pem 文件的绝对路径。

  4. [curl]
    ; A default value for the CURLOPT_CAINFO option. This is required to be an
    ; absolute path.
    ;curl.cainfo =
    curl.cainfo = "C:/php/cacert.pem"
    登录后复制
  5. (可选)重新启动 Web 服务器(例如Apache)重新加载 INI 文件。

这种方法的缺点是 cacert.pem 文件必须定期更新。 cacert.pem
例如,Curl 项目提供的文件是从根目录中提取的
由 Mozilla 维护的商店。平均而言,此列表和文件得到
每年更新4-5次。确保与最新root兼容
证书列表,请确保更新此文件的本地副本
定期

如果无法修改 INI 文件,请在 Curl 请求中指定 cacert.pem 文件的绝对路径:

 $ch = curl_init('https://php.watch');
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 curl_setopt($ch, CURLOPT_CAINFO, 'C:/php/cacert.pem');
 curl_exec($ch);
登录后复制

在 PHP 8.2 和 Curl 7.77 上,可以使用 CURLOPT_CAINFO_BLOB 选项获取包含 cacert.pem 内容的字符串。

以上就是如何修复 Windows 上的 PHP Curl HTTPS 证书颁发机构问题的详细内容,更多请关注php中文网其它相关文章!

https://www.php.cn/faq/1091457.html

发表回复

Your email address will not be published. Required fields are marked *