序言

先来看几个PHP的curl设置参数的文档解释:

  • CURLOPT_SSL_VERIFYPEER:禁用后cURL将终止从服务端进行验证。使用CURLOPT_CAINFO选项设置证书使用CURLOPT_CAPATH选项设置证书目录 如果CURLOPT_SSL_VERIFYPEER(默认值为2)被启用,CURLOPT_SSL_VERIFYHOST需要被设置成TRUE否则设置为FALSE。
  • CURLOPT_SSL_VERIFYHOST:1 检查服务器SSL证书中是否存在一个公用名(common name)。译者注:公用名(Common Name)一般来讲就是填写你将要申请SSL证书的域名 (domain)或子域名(sub domain)。2 检查公用名是否存在,并且是否与提供的主机名匹配。
  • CURLOPT_CAINFO:一个保存着1个或多个用来让服务端验证的证书的文件名。这个参数仅仅在和CURLOPT_SSL_VERIFYPEER一起使用时才有意义。

在大多数,们通过百毒这种搜索引擎搜出来的PHP的curl请求https接口出来的代码都会包含这一行:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

也就是关闭了ssl证书的有效性检测。实际上这并不是一种推荐的方案,因为这样存在被中间人获取你的信息的风险。

fiddler为什么能抓https

你可以先了解一下,为什么fiddler可以抓https的包内容:https://www.zhihu.com/question/24484809

  • 第一步, fiddler向服务器发送请求进行握手, 获取到服务器的CA证书, 用根证书公钥进行解密, 验证服务器数据签名, 获取到服务器CA证书公钥。
  • 第二步, fiddler伪造自己的CA证书, 冒充服务器证书传递给客户端浏览器, 客户端浏览器做跟fiddler一样的事。
  • 第三步, 客户端浏览器生成https通信用的对称密钥, 用fiddler伪造的证书公钥加密后传递给服务器, 被fiddler截获。
  • 第四步, fiddler将截获的密文用自己伪造证书的私钥解开, 获得https通信用的对称密钥。
  • 第五步, fiddler将对称密钥用服务器证书公钥加密传递给服务器, 服务器用私钥解开后建立信任, 握手完成, 用对称密钥加密消息, 开始通信。
  • 第六步, fiddler接收到服务器发送的密文, 用对称密钥解开, 获得服务器发送的明文。再次加密, 发送给客户端浏览器。
  • 第七步, 客户端向服务器发送消息, 用对称密钥加密, 被fidller截获后, 解密获得明文。

由于fiddler一直拥有通信用对称密钥, 所以在整个https通信过程中信息对其透明。

当然,上面的前提是,你的客户端需要安装fiddler的ca根证书,或信任所有的根证书。你安装了fiddler的根证书,fiddler就可以伪造任何网站的证书了。这也是为什么不要随意安装来路不明的根证书的原因,如果你随意安装了某些别有用心的人的根证书,那么你的https请求将相当于毫无安全性可言。

那么同样,上面的PHP的curl的不验证证书的参数将是大坑。

别人是怎么做的

们来看看facebook的sdk是怎么做的:https://github.com/facebook/php-graph-sdk/blob/master/src/Facebook/HttpClients/FacebookCurlHttpClient.php

CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_CAINFO => __DIR__ . '/certs/DigiCertHighAssuranceEVRootCA.pem',

facebook的ssl证书签发机构是DigiCert,所以他在他的sdk里面加入且仅加入了DigiCert的证书。这个时候通过fb的sdk发出去的https请求将只会使用这个DigiCert的根证书,也就避免了客户端被安装其他不信任的证书导致的中间人攻击的问题。通常对于SDK这种东西推荐使用这种强制指定根证书的方式。

如果你的根证书设置有误,你会收到CURL的这个错误:SSL certificate problem: unable to get local issuer certificate

关于可信证书

在php的curl配置参数里面还有这么一个配置,可以用来直接设置一个全局的ca证书的路径:

;curl.cainfo =

你可以在这里设置所有可信任的根证书的本地路径。这里有所有可信根证书的地址:https://curl.haxx.se/ca/cacert.pem

对于自己的服务器,怎么才能知道根证书的颁发者是谁呢?例如的网站:

image

从证书信息里面可以看到根证书是DST Root CA X3,或者的证书是Lets Encrypt颁发的,们去他的官网上找,有这么一个地址:https://letsencrypt.org/certificates/ 里面可以找到根证书的地址。

最后,再附Godaddy颁发的证书的根证书地址:https://certs.godaddy.com/repository

如果您觉得您在我这里学到了新姿势,博主支持转载,姿势本身就是用来相互学习的。同时,本站文章如未注明均为 hisune 原创 请尊重劳动成果 转载请注明 转自: 关于PHP的curl的ssl验证CURLOPT_SSL_VERIFYPEER及为什么需要验证ssl证书 - hisune.com