将 PHP cURL 与 SSL 证书一起使用时出错

2022-08-30 15:19:21

我正在尝试使用cURL编写一个PHP脚本,除了用户名和密码之外,还可以通过使用SSL证书的页面授权用户,我似乎无法通过SSL证书阶段。

在这种情况下,不幸的是,这不是一种选择。证书是身份验证的必需部分,否则我会收到其他类似SO帖子中提到的错误。curl_setopt($handle, CURLOPT_VERIFYPEER, 0)

我尝试了一些使用cURL的命令行运行:

> curl --url https://website

这将返回错误。如果我调整命令以包含该选项:(60) SLL certificate problem--cacert

> curl --url https://website --cacert /path/to/servercert.cer

它工作得很好;返回身份验证网站。

但是,我尝试了以下PHP代码:

$handle = curl_init();
$options = array( 
                  CURLOPT_RETURNTRANSFER => false,
                  CURLOPT_HEADER         => true,
                  CURLOPT_FOLLOWLOCATION => false,
                  CURLOPT_SSL_VERIFYHOST => '0',
                  CURLOPT_SSL_VERIFYPEER => '1',
                  CURLOPT_CAINFO         => '/path/to/servercert.cer',
                  CURLOPT_USERAGENT      => 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)',
                  CURLOPT_VERBOSE        => true,
                  CURLOPT_URL            => 'https://website'
           );

curl_setopt_array($handle, $options);
curl_exec($handle);
if (curl_errno($handle)) {
  echo 'Error: ' . curl_error($handle);
}
curl_close($handle);

我本来以为代码本质上类似于shell命令,但相反,我遇到了以下错误消息:

错误:设置证书验证位置时出错:CAfile:/path/to/servercert.cer CApath:none

我已经阅读了我能找到的所有文献(特别是在 php.net 和curl.haxx上),似乎找不到任何可以解决这个问题的东西。有什么建议吗?

我尝试过,但没有成功。但是,在通过 命令行而不是浏览器使用上述代码执行PHP脚本时,它可以完美地工作。任何解释为什么它在浏览器中不起作用?chmod 777 servercert.cerphp test.php


答案 1

因为事情通过命令行工作,而不是通过使用curl的php工作,那么我会追求curl是问题所在。

根据这个URL,http://curl.haxx.se/docs/sslcerts.html,这是你上面引用的SO帖子中引用的(阅读带有CURL(php)的SSL页面)...

“在 7.18.0 之前,curl 捆绑了一个严重过时的 ca 捆绑包文件,该文件是默认安装的。如今,卷曲档案根本没有ca证书。你需要把它们放到别处。例如,请参阅下文。

如果远程服务器使用自签名证书,如果您不安装 CA 证书捆绑包,如果服务器使用由 CA 签名的证书未包含在您使用的捆绑包中,或者如果远程主机是冒充您喜欢的站点的冒名顶替者,并且您希望从此服务器传输文件,请执行下列操作之一:"

然后,它继续列出您可以尝试的许多步骤。

由于您的 7.16.3 版本的 curl 早于 7.18.0,如果您还没有,我建议您更新 curl 和 openssl 组件,然后浏览上面引用的列表。


答案 2

详细阐述和总结一下:

如果您有一个使用PHP curl的PHP文件,并将系统的ca证书放在同一个目录中,下面的代码将为您提供一个快速启动

    $url = "https://myserver.mydomain.local/get_somedata.php";
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);

//These next lines are for the magic "good cert confirmation"
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    curl_setopt($ch, CURLOPT_VERBOSE, true);

//for local domains:
//you need to get the pem cert file for the root ca or intermediate CA that you signed all the domain certificates with so that PHP curl can use it...sorry batteries not included
//place the pem or crt ca certificate file in the same directory as the php file for this code to work
    curl_setopt($ch, CURLOPT_CAINFO, __DIR__.'/cafile.pem');
    curl_setopt($ch, CURLOPT_CAPATH, __DIR__.'/cafile.pem');

//DEBUG: remove slashes on the next line to prove "SSL verify" is the cause       
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

//Error handling and return result
    $data = curl_exec($ch);
    if ($data === false) {
        $result = curl_error($ch);
    } else {
        $result = $data;
    }

// Close handle
    curl_close($ch);
    return $result;

推荐