Paypal Access - SSL证书:无法获取本地颁发者证书

45

我正在使用cUrl和PHP向服务器请求(用于paypal访问)。

Paypal开发者网站从来没有提到过使用PayPal访问API需要SSL证书,但是我用来请求令牌的代码如下:

$options = array(
                CURLOPT_URL => $url,
                CURLOPT_POST => 1,
                CURLOPT_VERBOSE => 1,
                CURLOPT_POSTFIELDS => $postvals,
                CURLOPT_RETURNTRANSFER => 1,
                CURLOPT_SSLVERSION => 3
);

curl_setopt_array($ch, $options);

$response = curl_exec($ch); 
echo curl_error($ch);

这个回显会输出以下错误:

SSL certificate problem: unable to get local issuer certificate

我的问题是:

1)如果我只需要获取用户的电子邮件地址,那么使用Paypal访问是否需要SSL?

2)如果我不需要SSL,为什么会出现此错误?

PS:端点是以下内容:https://www.sandbox.paypal.com/webapps/auth/protocol/openidconnect/v1/tokenservice

4个回答

124

正确的解决方案是修复您的PHP设置。将CURLOPT_SSL_VERIFYPEER设置为false是一种快速解决方法,但它是错误的,因为它通过其证书颁发机构禁用了证书验证。这会使您容易受到中间人攻击。

修复很简单(php 5.3.7或更高版本) - 下载一个具有最新证书颁发机构列表的文件,并将此设置添加到您的php.ini
curl.cainfo=<path-to>cacert.pem

重启Web服务器,它就能工作了!


我已经在 /etc/ssl/certs/ca-certificates.crt(Gentoo Linux 发行版)位置上有一个类似的文件。 - Martin M.
3
在我的WAMP服务器设置中有效。谢谢。 - Robin Hood
13
另外,您可以在运行时指定证书:curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cacert.pem')。现在您已经没有理由禁用验证了! - Gras Double
这只是在Micah的PayPal .crt文件上发生的事情,日期为3-24-15。使用oori上面的“下载”链接快速更新.crt文件就解决了问题。 - iconMatrix
1
我下载了caert.pem文件并将其保存在C:\wamp\bin\php\php5.5.12中,具有正确的扩展名。 我还修改并取消注释了带有curl.cainfo路径的行,但我仍然得到相同的错误 :/ - JCarlosR
显示剩余9条评论

12

您可以通过添加以下内容来禁用SSL验证(从cURL 7.10开始,默认情况下启用):

CURLOPT_SSL_VERIFYPEER, false

将验证禁用添加到您的$options并不推荐,正确的做法是保持验证启用。

安全提示

如果远程站点使用已知CA颁发的证书但仍然无法通过验证,则很可能是远程服务器上证书设置不正确(缺少中间证书等)。 或者您的系统不知道签署目标证书的使用的证书颁发机构。在这种情况下,应该使用php.inicurl.cainfo (documentation)指向具有所有受支持的CA的有效PEM文件-这将使您的设置正确验证颁发者链。

请注意,通过将CURLOPT_SSL_VERIFYPEER设置为false您并没有解决问题! 您只是绕过了它。这些都与安全有关,因此在一段时间内这样做是可以的,但在生产环境中部署不明智,委婉地说,因为您将变得容易受到中间人攻击。你已经被警告了。


2
我认为-1并不合理,因为答案明确指出了安全性。 - Mister Verleg

5

我遇到了完全相同的问题

Can't connect to PayPal to validate IPN message: SSL certificate: unable to get local issuer certificate

我使用了Paypal在这里生成的代码样本(我使用PHP):https://github.com/paypal/ipn-code-samples 我下载了两个证书并尝试从curl测试两个证书:http://curl.haxx.se/docs/caextract.html 经过大约2小时的测试(使用Paypal的IPN模拟器)和搜索,发现Paypal IPN无法在本地主机上进行测试,因此我将代码推送到线上并尝试测试,但仍然遇到相同的错误(即使权限设置为777)。
当我设置CURLOPT_SSL_VERIFYPEER, false时,它可以工作,但这将使SSL证书失去意义。
在我的服务器文件中查找时,我在我的PHP文件夹中找到了一个curl-ca-bundle.crt文件。我决定在我的Paypal IPN脚本中硬编码CURLOPT_CAINFO到那个路径。最终它起作用了!
我注意到这个旧的.crt文件包含了一些最新的curl网站上没有的证书。这是来自verisign class 1、verisign class 2、verisign class 3和verisign class 4的一堆证书。

以下是我添加到curl的.crt文件中的完整证书名称列表:

  • Verisign Class 1 Public Primary Certification Authority
  • Verisign Class 1 Public Primary Certification Authority - G2
  • Verisign Class 1 Public Primary Certification Authority - G3
  • Verisign Class 2 Public Primary Certification Authority - G2
  • Verisign Class 2 Public Primary Certification Authority - G3
  • Verisign Class 3 Public Primary Certification Authority
  • Verisign Class 4 Public Primary Certification Authority - G2

这可能与@Andomar所说的有关——PayPal的Verisign证书不包含在默认(默认指curl的默认)安全证书列表中。

我没有时间调试并找出确切需要哪个证书,所以我只包含了所有证书。

如果将来有人遇到这个问题,我建议从curl获取最新的证书,并逐个添加上述列表中的证书,直到错误消失。
这里有一些维信证书的链接(您可能需要在Google上搜索未列出的其他证书):www.symantec.com/page.jsp?id=roots
注意*:要查看PayPal的当前证书,可以在终端中运行此命令:
openssl s_client -connect paypal.com:443 -showcerts

如果有人对这个问题有进一步的见解,请在评论区留言,因为我花了数小时才找出以上所有内容。

1
我通过从http://www.symantec.com/content/en/us/enterprise/verisign/roots/Class-3-Public-Primary-Certification-Authority.pem添加Verisign Class 3 Public Primary CA成功解决了问题 - 所以显然这就是缺失的那个。 - DiMono

2

SSL证书问题:无法获取本地发行者证书

这意味着cUrl不信任为PayPal提供担保的证书颁发机构Verisign。正如Marc B所评论的那样,cUrl不再内置对任何证书颁发机构的信任。

您可以使用选项绕过证书链验证:

CURLOPT_SSL_VERIFYPEER => 0

阅读如何配置cUrl以信任Verisign,请阅读cUrl文档


2
并不奇怪。curl现在不再内置任何CA证书,因此默认情况下它不信任任何人。 - Marc B
@MarcB:有趣,我原以为它使用操作系统的证书存储。 - Andomar
3
好的,但考虑到这家商店被保存在许多地方,让Curl变得有点偏执并认为每个人都在试图攻击它可能是最好的选择。 - Marc B
5
我会强烈反对任何人关闭主机/对等验证。相反,应下载cURL CA证书文件(http://curl.haxx.se/ca/cacert.pem)并将其包含在内。这样做解决问题同样很快,并且从长远来看可以更好地保护您。 - Robert
为什么我们应该相信这些证书。无意冒犯,只是说说而已。 - mydoglixu
我正在使用WAMP,我应该在哪里粘贴这行代码? - Gem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接