当前位置:首页 > PHP教程 > php高级应用 > 列表

PHP CURL访问HTTPS使用详解

发布:smiling 来源: PHP粉丝网  添加日期:2014-09-22 15:41:58 浏览: 评论:0 

如果你直接使用PHP CURL函数来抓取http内容可能没有任何问题了,但是如果你要正抓取的是https文件才会发现本文章帮你解决了一个大难题了,下面我们来看看具体操作过程.

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

https服务器post数据,代码如下:

  1. function curlPost($url$data$timeout = 30) 
  2.     $ssl = substr($url, 0, 8) == "https://" ? TRUE : FALSE; 
  3.     $ch = curl_init(); 
  4.     $opt = array
  5.             CURLOPT_URL     => $url
  6.             CURLOPT_POST    => 1, 
  7.             CURLOPT_HEADER  => 0, 
  8.             CURLOPT_POSTFIELDS      => (array)$data
  9.             CURLOPT_RETURNTRANSFER  => 1, 
  10.             CURLOPT_TIMEOUT         => $timeout
  11.             ); 
  12.     if ($ssl
  13.     { 
  14.         $opt[CURLOPT_SSL_VERIFYHOST] = 1; 
  15.         $opt[CURLOPT_SSL_VERIFYPEER] = FALSE; 
  16.     } 
  17.     curl_setopt_array($ch$opt); 
  18.     $data = curl_exec($ch); 
  19.     curl_close($ch); 
  20.     return $data
  21. $data = curlPost('https://www.phpfensi.com'array('p'=>'hello')); 
  22. echo ($data); 

其实这是告诉服务器不进行SSL认证,并不是真的走HTTPS,如果要真正使用HTTPS,那么需要提供CA证书.

上面关于SSL部分按照如下设置:

01.CURLOPT_SSL_VERIFYPEER 设置为 true,说明进行SSL证书认证  

02.CURLOPT_SSL_VERIFYHOST 设置为 2,说明进行严格认证  

03.CURLOPT_CAINFO 设置为证书的路径 

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

  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  //开源代码phpfensi.com 
  32.    
  33.     $ret = curl_exec($ch);   
  34.     //var_dump(curl_error($ch));  //查看报错信息   
  35.    
  36.     curl_close($ch);   
  37.     return $ret;     

如果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)查看具体错误信息,此时可以根据情况通过降低验证程度来保证正常访问,代码如下:

curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);

检查证书中是否设置域名,为0也可以,就是连域名存在与否都不验证了,平时我们使用浏览器访问各个https网站时,有时会遇到证书不受信的提示,其实就是因为这些网站的证书不是正规CA机构颁布的.

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

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

Tags: PHP CURL HTTPS使用

分享到: