Chinaunix首页 | 论坛 | 博客
  • 博客访问: 89454
  • 博文数量: 41
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 277
  • 用 户 组: 普通用户
  • 注册时间: 2013-01-14 11:43
文章分类

全部博文(41)

文章存档

2014年(4)

2013年(37)

我的朋友

分类: PHP

2013-08-26 17:17:31

三年前写过一篇《一个简陋的支持HTTPS的PHP CURL封装函数》,当时只是知其然不知其所以然,今天来详细梳理一下。

为方便说明,先上代码吧~ 这是今天重新封装的一个函数

点击(此处)折叠或打开

  1. /**
  2.  * curl POST
  3.  *
  4.  * @param string url
  5.  * @param array 数据
  6.  * @param int 请求超时时间
  7.  * @param bool HTTPS时是否进行严格认证
  8.  * @return string
  9.  */
  10. function curlPost($url, $data = array(), $timeout = 30, $CA = true){
  11.   
  12.     $cacert = getcwd() . '/cacert.pem'; //CA根证书
  13.     $SSL = substr($url, 0, 8) == "https://" ? true : false;
  14.       
  15.     $ch = curl_init();
  16.     curl_setopt($ch, CURLOPT_URL, $url);
  17.     curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
  18.     curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout-2);
  19.     if ($SSL && $CA) {
  20.         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); // 只信任CA颁布的证书
  21.         curl_setopt($ch, CURLOPT_CAINFO, $cacert); // CA根证书(用来验证的网站证书是否是CA颁布)
  22.         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // 检查证书中是否设置域名,并且是否与提供的主机名匹配
  23.     } else if ($SSL && !$CA) {
  24.         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 信任任何证书
  25.         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1); // 检查证书中是否设置域名
  26.     }
  27.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  28.     curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:')); //避免data数据过长问题
  29.     curl_setopt($ch, CURLOPT_POST, true);
  30.     curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  31.     //curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); //data with URLEncode
  32.   
  33.     $ret = curl_exec($ch);
  34.     //var_dump(curl_error($ch)); //查看报错信息
  35.   
  36.     curl_close($ch);
  37.     return $ret;
  38. }

如果URL地址是https打头,那就走SSL,否则就走普通的HTTP协议。

是否走HTTPS的话就安全了吗?其实SSL也有不同的验证程度。

例如需不需要验证证书中的公用名呢?(BTW:公用名(Common Name)一般来讲就是填写你将要申请SSL证书的域名 (domain)或子域名(sub domain)。)

需要验证主机名吗?

是任何证书都信任呢还是只信任CA颁布的呢?

(我擦嘞,电池快没点了,只捡关键地儿说了 - -|||)

如果网站SSL证书买的是CA的(通常比较贵),那么访问时可以使用比较严格的认证,即:


  1. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);   // 只信任CA颁布的证书  
  2. curl_setopt($ch, CURLOPT_CAINFO, $cacert); // CA根证书(用来验证的网站证书是否是CA颁布)  
  3. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // 检查证书中是否设置域名,并且是否与提供的主机名匹配  

如果网站的证书是自己生成的,或者是网上的小机构申请的,那么访问时如果使用严格认证则不会通过,直接返回false。(对了,返回false时可以打印curl_error($ch)查看具体错误信息。)此时可以根据情况通过降低验证程度来保证正常访问,例如:



  1. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 信任任何证书  
  2. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1); // 检查证书中是否设置域名(为0也可以,就是连域名存在与否都不验证了)  



平时我们使用浏览器访问各个https网站时,有时会遇到证书不受信的提示,其实就是因为这些网站的证书不是正规CA机构颁布的。

市面上各种浏览器中都内置了CA根证书列表信息,访问有CA颁布证书的网站时,会根据根证书验证这些网站的证书,所以就不会有这个提示了。

关于CA根证书文件,其实就是包含了各个主要CA机构的公钥证书,用来验证网站的证书是否是这些机构颁发的。

这里的这个文件是来源于mozilla的源码树,又转换成PEM格式证书文件。(大家可以到这里下载现成的http://curl.haxx.se/ca/cacert.pem

最后说一个和SSL无关的东西:


  1. curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));  

这个主要是为了解决POST时数据过长问题,具体参看之前的一篇博客《PHP CURL POST无法获取响应内容的问题》

http://blog.csdn.net/linvo/article/details/8816079

阅读(1296) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~