简体   繁体   English

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

[英]Error using PHP cURL with SSL certificates

I'm trying to write a PHP script using cURL that can authorize a user through a page that uses an SSL certificate, in addition to username and password, and I can't seem to get past the SSL cert stage.我正在尝试使用 cURL 编写一个 PHP 脚本,该脚本可以通过使用 SSL 证书的页面以及用户名和密码来授权用户,但我似乎无法通过 SSL 证书阶段。

In this case, curl_setopt($handle, CURLOPT_VERIFYPEER, 0) unfortunately isn't an option.在这种情况下, curl_setopt($handle, CURLOPT_VERIFYPEER, 0)不幸的是不是一个选项。 The certificate is a required part of authentication, otherwise I get the error mentioned in this other similar SO post .证书是身份验证的必需部分,否则我会收到其他类似的 SO 帖子中提到的错误。

I've tried a few command-line runs with cURL:我已经尝试了一些带有 cURL 的命令行运行:

> curl --url https://website

This returns the (60) SLL certificate problem error.这将返回(60) SLL certificate problem错误。 If I adjust the command to include the --cacert option:如果我调整命令以包含--cacert选项:

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

It works just fine;它工作得很好; the auth website is returned.返回 auth 网站。

However, I've tried the following PHP code:但是,我尝试了以下 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);

I would have thought the code was essentially analogous to the shell commands, but instead I'm greeted with the following error message:我原以为代码本质上类似于 shell 命令,但我收到了以下错误消息:

Error: error setting certificate verify locations: CAfile: /path/to/servercert.cer CApath: none错误:错误设置证书验证位置:CAfile:/path/to/servercert.cer CApath:none

I've read all the literature I can find (particularly on php.net and curl.haxx) and can't seem to find anything that fixes this problem.我已经阅读了我能找到的所有文献(特别是在 php.net 和 curl.haxx 上),但似乎找不到任何可以解决这个问题的东西。 Any suggestions?有什么建议么?

I have tried chmod 777 servercert.cer with no success.我试过chmod 777 servercert.cer没有成功。 However, in executing the PHP script with the above code from the command line instead of the browser via php test.php , it works perfectly.但是,在通过php test.php从命令行而不是浏览器中使用上述代码执行 PHP 脚本时,它运行良好。 Any explanation for why it doesn't work in the browser?为什么它在浏览器中不起作用的任何解释?

Because things work via the command line but not via php using curl then I would pursue curl being the problem.因为事情是通过命令行而不是通过 php 使用 curl 工作的,所以我会追求 curl 是问题所在。

According to this URL, http://curl.haxx.se/docs/sslcerts.html , which was reference in an SO post you cited above ( reading SSL page with CURL (php) )...根据此 URL, http://curl.haxx.se/docs/sslcerts.html ,这是您在上面引用的 SO 帖子中的参考( 使用 CURL (php) 阅读 SSL 页面)...

"Until 7.18.0, curl bundled a severely outdated ca bundle file that was installed by default. These days, the curl archives include no ca certs at all. You need to get them elsewhere. See below for example. “直到 7.18.0,curl 捆绑了一个默认安装的严重过时的 ca 包文件。如今,curl 档案根本不包含 ca 证书。您需要在其他地方获取它们。例如,请参见下文。

If the remote server uses a self-signed certificate, if you don't install a CA cert bundle, if the server uses a certificate signed by a CA that isn't included in the bundle you use or if the remote host is an impostor impersonating your favorite site, and you want to transfer files from this server, do one of the following:"如果远程服务器使用自签名证书,如果您未安装 CA 证书捆绑包,如果服务器使用由 CA 签名的证书(未包含在您使用的捆绑包中)或远程主机是冒名顶替者冒充您最喜欢的站点,并且您想要从此服务器传输文件,请执行以下操作之一:”

It then goes on to list a number of steps that you can try.然后继续列出您可以尝试的一些步骤。

Since your 7.16.3 version of curl is prior to 7.18.0, if you haven't already, I would recommend updating your curl and openssl components and then working through the list referenced above.由于您的 curl 7.16.3 版本早于 7.18.0,如果您还没有,我建议您更新 curl 和 openssl 组件,然后完成上面引用的列表。

After 6 years of the question, I meet the same problem on a shared-host, and apparently there is no satisfactory answer.提问 6 年后,我在共享主机上遇到了同样的问题,显然没有令人满意的答案。 I found for myself a solution, hope it useful for everybody.我为自己找到了一个解决方案,希望对大家有用。

You can try this config:你可以试试这个配置:

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');

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

It's work with me.这是和我一起工作。 But note, the CA file must be place in accessable dir (with chmod 755 or 777) and it will better if CA file is in the same dir with PHP file.但请注意,CA 文件必须放在可访问的目录中(使用 chmod 755 或 777),如果 CA 文件与 PHP 文件在同一目录中会更好。

To elaborate and sum this up:对此进行阐述和总结:

if you have a PHP file using PHP curl and place the ca certificate for your systems in the same directory, the below code will give you a jumpstart如果您有一个使用 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;

Now that this question is vey old, but maybe could be useful for some users looking for an answer currently.现在这个问题已经很老了,但可能对一些目前正在寻找答案的用户有用。

I have a similar problem about an API with SSL, having problems with CURL (not with the browsers) my problem was that I just put the certificate but not the ceritifcates chain/bundle.我有一个关于带有 SSL 的 API 的类似问题,CURL 有问题(不是浏览器)我的问题是我只放置了证书而不是证书链/捆绑包。 Then I put that and things started working.然后我把它放进去,事情就开始起作用了。 So that's important in order to avoid problems.所以这对于避免问题很重要。

Hope this can be useful for someone.希望这对某人有用。

You can try this if it works for you:如果它适合你,你可以试试这个:

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');

Comment these lines and add this:注释这些行并添加以下内容:

//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');

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM