使用PHP cURL和SSL证书时出错

时间:2009-04-08 18:00:50

标签: php ssl curl certificate

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

在这种情况下,遗憾的是curl_setopt($handle, CURLOPT_VERIFYPEER, 0)不是一种选择。证书是身份验证的必需部分,否则我会收到this other similar SO post中提到的错误。

我尝试过使用cURL进行一些命令行运行:

> curl --url https://website

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

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

它运作得很好;返回auth网站。

但是,我尝试了以下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上)并且似乎无法找到解决此问题的任何内容。有什么建议吗?

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

编辑2 :这些只有足够勇敢回答这个问题的灵魂的驱逐者投票才会变老。请提供有意义的内容或传递给我们。

5 个答案:

答案 0 :(得分:13)

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

根据此网址http://curl.haxx.se/docs/sslcerts.html,您在上面引用的SO帖子中引用了reading SSL page with CURL (php))...

“直到7.18.0,curl捆绑了一个严重过时的ca包文件 默认安装。这些天,卷曲档案包括没有ca证书 所有。你需要把它们带到其他地方。例如,见下文。

如果远程服务器使用自签名证书,则表明您未安装CA. cert bundle,如果服务器使用由CA签名但未使用的证书 包含在您使用的包中或远程主机是冒名顶替者 模仿您最喜欢的网站,并希望从中传输文件 服务器,执行以下操作之一:“

然后继续列出您可以尝试的一些步骤。

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

答案 1 :(得分:5)

经过6年的提问,我在共享主机上遇到了同样的问题,显然没有令人满意的答案。我找到了一个解决方案,希望它对每个人都有用。

您可以尝试此配置:

curl_setopt($config,CURLOPT_SSL_VERIFYHOST,0);
curl_setopt($config,CURLOPT_SSL_VERIFYPEER,1);
curl_setopt($config,CURLOPT_CAINFO,'ca-bundle.crt');
curl_setopt($config,CURLOPT_CAPATH,'ca-bundle.crt');

我遇到了与@Magsol相同的错误:Error: error setting certificate verify locations: CAfile: /path/to/servercert.cer CApath: none;所以我添加了第4行来设置CAPath。

它与我合作。但请注意,CA文件必须放在可访问的目录中(使用chmod 755或777),如果CA文件与PHP文件位于同一目录中,则会更好。

答案 2 :(得分:3)

既然这个问题已经过时了,但对于目前正在寻找答案的一些用户来说可能会有用。

我对使用SSL的API有类似的问题,有CURL问题(不是浏览器)我的问题是我只是放了证书而不是ceritifcates链/捆绑。然后我把它放了,事情就开始了。所以这对于避免问题很重要。

希望这对某人有用。

答案 3 :(得分:3)

详细说明并总结:

如果你有一个使用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
    if (curl_exec($ch) === false)
      {
       $result = curl_error($ch);
      }
    else
      {
       $result = curl_exec($ch);
      }
    // Close handle
    curl_close($ch);
    return $result;

答案 4 :(得分:0)

如果它适合您,您可以尝试以下方法:

curl_setopt($ch, CURLOPT_URL, "https://test.example.com/v1/authenticate.json?api_key=123456");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_CAINFO,'cert.embedapp.20191004.pem');
curl_setopt($ch,CURLOPT_CAPATH,'./cert.embedapp.20191004.pem');

注释这些行并添加以下内容:

//curl_setopt($ch,CURLOPT_CAINFO,'cert.embedapp.20191004.pem');
//curl_setopt($ch,CURLOPT_CAPATH,'./cert.embedapp.20191004.pem');
curl_setopt($ch, CURLOPT_SSLCERT,'cert.embedapp.20191004.pem');