2017-05-19 171 views
0

我嘗試使用PHP的cURL登錄到https://digitalgamingleague.co.za,但遇到問題。代碼的主要部分如下。我真的不知道如何使用cURL,因此,anyhelp將不勝感激。PHP cURL登錄網站

$username = get_option('wp_dgl_dgl_username'); 
$password = get_option('wp_dgl_dgh_password'); 

if (is_null($username) or is_null($password)) 
{ 
    return "Please check the settings!"; 
} 

//set the directory for the cookie using defined document root var 
$dir = plugin_dir_path(__FILE__); 
//build a unique path with every request to store 
//the info per user with custom func. 
$path = $dir; 

$cookie_file_path = $path."/cookies.txt"; 

$url="https://www.digitalgamingleague.co.za/"; 

$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, $url); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 

curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file_path); 
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file_path); 

$start = curl_exec($ch); 
$startinfo = curl_getinfo($ch); 
$starterror = curl_error($ch); 
curl_close($ch); 

//login form action url 
$url="https://www.digitalgamingleague.co.za/login/"; 
$postinfo = "password=" . $password . "&username=" . $username . "&remember=1&_from=https://digitalgamingleague.co.za/api/&_csrf="; 

$request_headers = [ 
    'Accept: */*', 
    'Accept-Encoding: gzip, deflate', 
    'Content-Type: application/x-www-form-urlencoded', 
]; 

$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, $url); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 

//curl_setopt($ch, CURLOPT_HEADER, true); 
//curl_setopt($ch, CURLOPT_NOBODY, false); 
curl_setopt($ch, CURLOPT_URL, $url); 
//curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); 

curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file_path); 
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file_path); 
//set the cookie the site has for certain features, this is optional 
//curl_setopt($ch, CURLOPT_COOKIE, "cookiename=0"); 
//curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7"); 
//curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 
//curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
//curl_setopt($ch, CURLOPT_REFERER, $_SERVER['REQUEST_URI']); 
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 

//curl_setopt($ch, CURLOPT_AUTOREFERER, true); 
//curl_setopt($ch, CURLOPT_FAILONERROR, true); 
//curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers); 
//curl_setopt($ch, CURLOPT_ENCODING, ""); 
//curl_setopt($ch, CURLINFO_HEADER_OUT, true); 

//curl_setopt($ch, CURLOPT_MAXREDIRS , 30); 

//curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); 
curl_setopt($ch, CURLOPT_POST, 1); 
curl_setopt($ch, CURLOPT_POSTFIELDS, $postinfo); 
$login = curl_exec($ch); 
$logininfo = curl_getinfo($ch); 
$loginerror = curl_error($ch); 
curl_close($ch); 

$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, $url); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 

curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file_path); 
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file_path); 

//page with the content I want to grab 
curl_setopt($ch, CURLOPT_POST, 0); 
curl_setopt($ch, CURLOPT_POSTFIELDS, ""); 
//curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); 
curl_setopt($ch, CURLOPT_URL, "https://www.digitalgamingleague.co.za/api/cups"); 
//do stuff with the info with DomDocument() etc 
$cups_raw = curl_exec($ch); 

$info = curl_getinfo($ch); 
$error = curl_error($ch); 
curl_close($ch); 
    return "<strong>Start</strong>: <br>" . $start . "<br><em>Info</em>: <br>" . $startinfo . "<br><em>Error</em>: <br>" . $starterror . "<br><strong>Login</strong>: <br>" . $login . "<br><em>Info</em>: <br>" . $logininfo . "<br><em>Error</em>: <br>" . $loginerror . "<br><strong>Cups</strong>: <br>" . $cups_raw . "<br><em>Info</em>: <br>" . $info . "<br><em>Error</em>: <br>" . $error; 

The Mostly Source Code

回答

0

當你寫一個客戶端的API(或服務器),你必須親手做您的瀏覽器所做的工作:保持頭,並添加所有的人都在您的要求。

+0

常見的異常包括'內容encoding',不用手動設置標題,除非你真的打算手工處理那些編碼(但爲什麼你會嗎?你可以通過設置CURLOPT_ENCODING來自動發送頭文件並自動解碼)和'content-type',don如果你打算使用'application/x-www-form-urlencoded'或者'multipart/form-data'編碼,那麼手動設置就比較容易出錯,而不是自動設置curl。和'User-Agent'頭部。它更安全地設置CURLOPT_USERAGENT,所以你不要忘記下一個請求 – hanshenrik

2

你做了幾個失誤,

  • 你不URL編碼的用戶名/密碼,甚至是硬編碼from參數的編碼錯誤(它實際上應該是&from=https%3A%2F%2Fdigitalgamingleague.co.za%2Fapi%2F%26_csrf%3D),解決這個問題。要麼使用urlencode(),要麼使用http_build_query更好。

  • 你對服務器說你接受gzip and deflate編碼,但是如果服務器決定使用任何這些編碼,你不提供解碼它的代碼。處理這個問題的最好方法是將CURLOPT_ENCODING設置爲空字符串,並且curl將自動地accept-encoding: <all encodings that libcurl was compiled with here>,並且如果需要的話,爲您解碼。

  • 你手動設置了'Content-Type: application/x-www-form-urlencoded',頭,這不是必需的,並且容易出錯,libcurl會自動檢測x-www-form-urlencoded編碼,並設置頭文件,如果你正確地編碼了url不是 - 請參閱上面有關urlencoding的案例)

  • 在發送登錄請求之前,您需要一個會話cookie和一個csrf標記,否則服務器將拒絕您的請求,認爲它是CSRF黑客攻擊嘗試,並且您提供否代碼來獲取csrf標記。你應該使用一個html解析器(如DOMDocument)來解壓縮它。

  • 如果登錄成功,但服務器實際響應http 302 Found重定向響應,但您沒有提供處理http重定向響應的代碼。處理這些最簡單的方法是設置CURLOPT_FOLLOWLOCATION - 它出現在你的代碼中,但只在註釋中。

  • 您在登錄時不提供任何引用標頭,可能需要您提供它。以啓用最好的辦法,是CURLOPT_AUTOREFERER

這裏的工作的例子,使用從https://github.com/divinity76/hhb_.inc.php/blob/master/hhb_.inc.php的hhb_curl類(和[email protected]賬戶僅僅是一個虛擬賬戶我爲測試創建的,所以在它被泄露沒有壞處,其時,我在這裏發表的憑據顯然發生。)

<?php 
declare(strict_types = 1); 
require_once ('hhb_.inc.php'); 
$hc = new hhb_curl(); 

$hc->_setComfortableOptions(); 
$hc->exec ('https://digitalgamingleague.co.za/login'); // << getting a referer, csrf token, and a session. 
$domd = @DOMDocument::loadHTML ($hc->getResponseBody()); 
$csrf = NULL; 

// extract the csrf token.. 
foreach ($domd->getElementsByTagName ("form") as $form) { 
    if ($form->getAttribute ("action") === '/login') { 
     foreach ($form->getElementsByTagName ("input") as $input) { 
      if ($input->getAttribute ("name") === '_csrf') { 
       $csrf = $input->getAttribute ("value"); 
       break 2; 
      } 
     } 
    } 
} 
if ($csrf === NULL) { 
    throw new \RuntimeException ('failed to extract the csrf token!'); 
} 
$hc->setopt_array (array (
     CURLOPT_POST => true, 
     CURLOPT_POSTFIELDS => http_build_query (array (
       '_csrf' => $csrf, 
       'from' => '${param.from}', // << no idea what that's supposed to mean, probably a web dev error 
       'username' => '[email protected]', 
       'password' => '[email protected]', 
       'rememberMe' => 1 
     )) 
)); 

$hc->exec ('https://digitalgamingleague.co.za/login'); 
hhb_var_dump ($hc->getStdErr(), $hc->getResponseBody());