我的答案只適用於表單身份驗證(這是最常見的身份驗證形式)。
基本上,當你瀏覽一個網站時,你會在其上打開一個「會話」。當你在網站上登錄時,你的會話將被「認證」,並且基於此你將被授予訪問權限。
由於存儲在cookie中的會話ID,您的瀏覽器可以識別與服務器相應的會話。
所以你必須瀏覽登錄頁面,然後瀏覽你想要的頁面,而不忘記在這個過程中發送cookie。 Cookie是您瀏覽的所有網頁之間的鏈接。
我實際上遇到了你剛剛做的同樣的問題,並寫了一個類來做到這一點,而不必記住這個cookie的事情。
快速看看課堂,這不重要,但請看下面的例子。它允許您提交實施CSRF保護的表單。
該類基本上具有以下功能: - 符合基於CSRF令牌的保護 - 發送「通用」用戶代理。某些網站拒絕不與用戶代理通信的查詢 - 發送推薦頭。一些網站拒絕不通信的引用(這是另一個反CSRF保護) 查詢 - 各地的商店中調用
文件餅乾:WebClient.php
<?php
/**
* Webclient
*
* Helper class to browse the web
*
* @author Bgi
*/
class WebClient
{
private $ch;
private $cookie = '';
private $html;
public function Navigate($url, $post = array())
{
curl_setopt($this->ch, CURLOPT_URL, $url);
curl_setopt($this->ch, CURLOPT_COOKIE, $this->cookie);
if (!empty($post)) {
curl_setopt($this->ch, CURLOPT_POST, TRUE);
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $post);
}
$response = $this->exec();
if ($response['Code'] !== 200) {
return FALSE;
}
//echo curl_getinfo($this->ch, CURLINFO_HEADER_OUT);
return $response['Html'];
}
public function getInputs()
{
$return = array();
$dom = new DOMDocument();
@$dom->loadHtml($this->html);
$inputs = $dom->getElementsByTagName('input');
foreach($inputs as $input)
{
if ($input->hasAttributes() && $input->attributes->getNamedItem('name') !== NULL)
{
if ($input->attributes->getNamedItem('value') !== NULL)
$return[$input->attributes->getNamedItem('name')->value] = $input->attributes->getNamedItem('value')->value;
else
$return[$input->attributes->getNamedItem('name')->value] = NULL;
}
}
return $return;
}
public function __construct()
{
$this->init();
}
public function __destruct()
{
$this->close();
}
private function init()
{
$this->ch = curl_init();
curl_setopt($this->ch, CURLOPT_USERAGENT, "Mozilla/6.0 (Windows NT 6.2; WOW64; rv:16.0.1) Gecko/20121011 Firefox/16.0.1");
curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($this->ch, CURLOPT_MAXREDIRS, 5);
curl_setopt($this->ch, CURLINFO_HEADER_OUT, TRUE);
curl_setopt($this->ch, CURLOPT_HEADER, TRUE);
curl_setopt($this->ch, CURLOPT_AUTOREFERER, TRUE);
}
private function exec()
{
$headers = array();
$html = '';
ob_start();
curl_exec($this->ch);
$output = ob_get_contents();
ob_end_clean();
$retcode = curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
if ($retcode == 200) {
$separator = strpos($output, "\r\n\r\n");
$html = substr($output, $separator);
$h = trim(substr($output,0,$separator));
$lines = explode("\n", $h);
foreach($lines as $line) {
$kv = explode(':',$line);
if (count($kv) == 2) {
$k = trim($kv[0]);
$v = trim($kv[1]);
$headers[$k] = $v;
}
}
}
// TODO: it would deserve to be tested extensively.
if (!empty($headers['Set-Cookie']))
$this->cookie = $headers['Set-Cookie'];
$this->html = $html;
return array('Code' => $retcode, 'Headers' => $headers, 'Html' => $html);
}
private function close()
{
curl_close($this->ch);
}
}
我如何使用它?
在這個例子中,我登錄到網站,然後瀏覽到包含一個表單來上傳文件的頁面,然後我上傳的文件:
<?php
require_once('WebClient.php');
$url = 'http://example.com/administrator/index.php'; // This a Joomla admin
$wc = new WebClient();
$page = $wc->Navigate($url);
if ($page === FALSE) {
die('Failed to load login page.');
}
echo('Logging in...');
$post = $wc->getInputs();
$post['username'] = $username;
$post['passwd'] = $passwd;
$page = $wc->Navigate($url, $post);
if ($page === FALSE) {
die('Failed to post credentials.');
}
echo('Initializing installation...');
$page = $wc->Navigate($url.'?option=com_installer');
if ($page === FALSE) {
die('Failed to access installer.');
}
echo('Installing...');
$post = $wc->getInputs();
$post['install_package'] = '@'.$file; // The @ specifies we are sending a file
$page = $wc->Navigate($url.'?option=com_installer&view=install', $post);
if ($page === FALSE) {
die('Failed to upload file.');
}
echo('Done.');
的導航()方法將返回FALSE要麼瀏覽頁面的HTML內容。
呵呵,還有最後一件事:不要用正則表達式來解析HTML,這是錯誤的。有一個傳說中的StackOverflow答案:請參閱here。
將用戶名和密碼組合功能放入您的搜尋器中。隨着一個非常長的隨機不可猜測的密碼。很確定,如果不登錄,您無法抓取安全網頁。這會打破目的。 – PenguinCoder
自動調情?聽起來就像你試圖濫用這個系統。 – Joe
我有用戶名和密碼 – Shawon