您現在的位置: 365建站網 > 365學習 > PHP實現抓取HTTPS內容和curl訪問https示例分享

PHP實現抓取HTTPS內容和curl訪問https示例分享

文章來源:365jz.com     點擊數:746    更新時間:2017-12-25 23:30   參與評論

最近在研究Hacker News API時遇到一個HTTPS問題。因為所有的Hacker News API都是通過加密的HTTPS協議訪問的,跟普通的HTTP協議不同,當使用PHP里的函數 file_get_contents() 來獲取API里提供的數據時,出現錯誤,使用的代碼是這樣的:

<?php
$data = file_get_contents("https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty");
......

當運行上面的代碼是遇到下面的錯誤提示:

PHP Warning:  file_get_contents(): Unable to find the wrapper "https" - did you forget to enable it when you configured PHP?

下面是截圖:

php https error

為什么會出現這樣的錯誤?

在網上經過一番搜索,發現遇到這樣錯誤的人還不少,問題很直接,是因為在PHP的配置文件里沒有開啟一個參數,在我本機上是 /apache/bin/php.ini 里的 ;extension=php_openssl.dll 這一項,需要將前面的分號去掉。你可以用下面的腳本來檢查你的PHP環境的配置:

$w = stream_get_wrappers();
echo 'openssl: ',  extension_loaded  ('openssl') ? 'yes':'no', "\n";
echo 'http wrapper: ', in_array('http', $w) ? 'yes':'no', "\n";
echo 'https wrapper: ', in_array('https', $w) ? 'yes':'no', "\n";
echo 'wrappers: ', var_dump($w);

運行上面的這個腳本片段,在我的機器上得到的結果是:

openssl: no
http wrapper: yes
https wrapper: no
wrappers: array(10) {
  [0]=>
  string(3) "php"
  [1]=>
  string(4) "file"
  [2]=>
  string(4) "glob"
  [3]=>
  string(4) "data"
  [4]=>
  string(4) "http"
  [5]=>
  string(3) "ftp"
  [6]=>
  string(3) "zip"
  [7]=>
  string(13) "compress.zlib"
  [8]=>
  string(14) "compress.bzip2"
  [9]=>
  string(4) "phar"
}

替代方案

發現錯誤,改正錯誤,這很簡單,困難的是,發現錯誤后無法改正錯誤。我原本是想將這個腳本方法遠程主機上,但我無法修改遠程主機的PHP配置,結果是,我無法使用這一方案,但我們不能在一棵樹上吊死,這條路走不通,看看有沒有其它路。

另外一個我經常用的PHP里抓取內容的函數是 curl ,它比 file_get_contents() 更強大,提供了很多的可選參數。對于訪問 HTTPS 內容的問題,我們需要使用的 CURL 配置參數是:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

你可以從語義上看出,它是忽略/跳過了SSL安全驗證。也許這不是一個很好的做法,但對于普通的場景中,這幾經足夠了。

下面是利用 Curl 封裝的一個能訪問HTTPS內容的函數:

function getHTTPS($url) {
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  curl_setopt($ch, CURLOPT_HEADER, false);
  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_REFERER, $url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  $result = curl_exec($ch);
  curl_close($ch);
  return $result;
}

以上就是php獲取https內容的全部過程了,很簡單很實用,推薦給有相同項目需求的小伙伴。
 

php使用curl訪問https示例分享

為方便說明,先上代碼吧

 

/** 
 * curl POST 
 * 
 * @param   string  url 
 * @param   array   數據 
 * @param   int     請求超時時間 
 * @param   bool    HTTPS時是否進行嚴格認證 
 * @return  string 
 */  
function curlPost($url, $data = array(), $timeout = 30, $CA = true){    

    $cacert = getcwd() . '/cacert.pem'; //CA根證書  
    $SSL = substr($url, 0, 8) == "https://" ? true : false;  

    $ch = curl_init();  
    curl_setopt($ch, CURLOPT_URL, $url);  
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);  
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout-2);  
    if ($SSL && $CA) {  
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);   // 只信任CA頒布的證書  
        curl_setopt($ch, CURLOPT_CAINFO, $cacert); // CA根證書(用來驗證的網站證書是否是CA頒布)  
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // 檢查證書中是否設置域名,并且是否與提供的主機名匹配  
    } else if ($SSL && !$CA) {  
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 信任任何證書  
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1); // 檢查證書中是否設置域名  
    }  
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:')); //避免data數據過長問題  
    curl_setopt($ch, CURLOPT_POST, true);  
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);  
    //curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); //data with URLEncode  

    $ret = curl_exec($ch);  
    //var_dump(curl_error($ch));  //查看報錯信息  

    curl_close($ch);  
    return $ret;    
}    

 

如果URL地址是https打頭,那就走SSL,否則就走普通的HTTP協議。

是否走HTTPS的話就安全了嗎?其實SSL也有不同的驗證程度。

例如需不需要驗證證書中的公用名呢?(BTW:公用名(Common Name)一般來講就是填寫你將要申請SSL證書的域名 (domain)或子域名(sub domain)。)

需要驗證主機名嗎?

是任何證書都信任呢還是只信任CA頒布的呢?

(我擦嘞,電池快沒點了,只撿關鍵地兒說了 - -|||)

如果網站SSL證書買的是CA的(通常比較貴),那么訪問時可以使用比較嚴格的認證,即:

 

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);   // 只信任CA頒布的證書 
curl_setopt($ch, CURLOPT_CAINFO, $cacert); // CA根證書(用來驗證的網站證書是否是CA頒布) 
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // 檢查證書中是否設置域名,并且是否與提供的主機名匹配

 

如果網站的證書是自己生成的,或者是網上的小機構申請的,那么訪問時如果使用嚴格認證則不會通過,直接返回false。(對了,返回false時可以打印curl_error($ch)查看具體錯誤信息。)此時可以根據情況通過降低驗證程度來保證正常訪問,例如:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 信任任何證書 
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1); // 檢查證書中是否設置域名(為0也可以,就是連域名存在與否都不驗證了)

 

平時我們使用瀏覽器訪問各個https網站時,有時會遇到證書不受信的提示,其實就是因為這些網站的證書不是正規CA機構頒布的。

市面上各種瀏覽器中都內置了CA根證書列表信息,訪問有CA頒布證書的網站時,會根據根證書驗證這些網站的證書,所以就不會有這個提示了。

關于CA根證書文件,其實就是包含了各個主要CA機構的公鑰證書,用來驗證網站的證書是否是這些機構頒發的。

這里的這個文件是來源于mozilla的源碼樹,又轉換成PEM格式證書文件。(大家可以到這里下載現成的http://curl.haxx.se/ca/cacert.pem)

最后說一個和SSL無關的東西:

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

這個主要是為了解決POST時數據過長問題

如對本文有疑問,請提交到交流論壇,廣大熱心網友會為你解答??! 點擊進入論壇


發表評論 (746人查看,0條評論)
請自覺遵守互聯網相關的政策法規,嚴禁發布色情、暴力、反動的言論。
用戶名: 驗證碼: 點擊我更換圖片
最新評論
------分隔線----------------------------
自拍偷拍福力视频,偷拍国际精品,麻豆一区福利电影,国产网红视频午夜福利,se视频大全,久久国产AV影院 亚洲日韩亚洲另类激情文学| 快穿男神有点燃免费阅读| 国产又黄又潮娇喘视频| 6一12泑女www| 日韩精品人妻无码一区二区三区| 欧洲日韩av无线在码| 国产女厕所偷窥系列在线视频| 中文字幕精品无码一区二区三区| 欧美性xxxxx极品| 啊!摁摁~啊!用力~快点视频| yy6080理论片在线大全| 久久精品伊人一区二区三区| 国产手机在线αⅴ片无码观看| 日本又色又爽又黄的三级视频| 一本到高清视频在线观看三区| 操美女| 720lu国产刺激无码| 97亚洲色欲色欲综合网| 欧美黑人性暴力猛交| 欧美高清videossexo18| 97国产理论影院| 欧美色视频日本片免费| xxfree 性欧美hd| 国产亚洲欧美在线专区| 污污又黄又爽免费的网站| 亚洲精品无码久久| 狠狠色丁香婷婷久久综合| 免费人成网站在线观看| 97超碰国产精品最新| 中文文字幕文字幕永久免费| 亚洲粉嫩高潮18p| http://www.irenechow.com