2016-03-17 8 views
2

Я хочу, чтобы войти в систему из PHP сценария на другой сайт, но я всегда получаю такой ответ:Войти с PHP локон и CSRF токена

403 Error: CSRF token mismatch 

извлечь маркер CSRF из скрытого поля на веб-сайте, но это, кажется, это неправильно. Это мой код:

$username = "testuser"; 
$password = "testpass"; 

$path = "c:\\test\\"; 
$url="http://itw.me/login"; 

$field='_csrf'; 
$html=file_get_contents($url); 

libxml_use_internal_errors(true); 
$dom=new DOMDocument; 
$dom->validateOnParse=false; 
$dom->recover=true; 
$dom->formatOutput=false; 
$dom->loadHTML($html); 
libxml_clear_errors(); 
$xpath=new DOMXPath($dom); 
$col=$xpath->query('//input[@name="'.$field.'"]'); 
foreach($col as $node) $csrftoken=$node->getAttribute('value'); 
echo "-".$csrftoken."-"; 

$postinfo = "email=".$username."&password=".$password."&_csrf=".$csrftoken; 
$cookie_file_path = $path."/cookie.txt"; 

$ch = curl_init(); 
curl_setopt($ch, CURLOPT_HEADER, false); 
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_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_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_REFERER, $_SERVER['REQUEST_URI']); 
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0); 
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); 
curl_setopt($ch, CURLOPT_POST, 1); 
curl_setopt($ch, CURLOPT_POSTFIELDS, $postinfo); 
curl_exec($ch); 

curl_setopt($ch, CURLOPT_URL, "http://itw.me"); 
$html = curl_exec($ch); 
print($html); 
curl_close($ch); 
+0

Получаете ли вы что-нибудь в строке с эхом «-». $ Csrftoken. "-"; – Gerfried

+0

Да, я получаю токен crsf, но это кажется действительным только для первой pageload, где я беру этот токен. – vc0

ответ

3

Вы делаете первый запрос с file_get_contents и ваш второй запрос cURL.

Вы создали кувшин для печенья для второго запроса, но не для первого запроса. Следовательно, каждый из этих двух запросов начинает новую сессию.

Точки CSRF хранятся в сеансе сервером, на который вы делаете запрос, поэтому токен, который вы получаете первым, не будет соответствовать токену в сеансе для второго запроса.

Вам нужно:

  • Использование Curl последова-
  • Используйте тот же куков для обоих запросов
0

Идентификатор CSRF, предназначенный для каждой сессии. Прочитать первый комментарий ot yor question (комментарий @walkingRed) (комментарий удален - cURL CSRF Token - это решение). Есть решение вашей проблемы.

Вы должны начать сеанс на другом веб-сайте, после чего вы можете получить правильный токен csrf.

И важно использовать файлы cookie с каждым запросом, чтобы определить, что ваш внешний запрос всегда находится в одном сеансе.

Пример:

Вы делаете первый запрос, чтобы захватить CSRF токен. На внешнем веб-сайте был запущен новый сеанс для вашего запроса и сгенерирован токен csrf.

Затем вы делаете запрос anohter, но без использования файлов cookie - для этого reuqest снова начал новый сеанс и снова сгенерировал новый токен csrf для этого нового сеанса.

1

теперь работает!

$username = "user"; 
$password = "pass"; 
$url = "http://url.com/login"; 
$cookie= "c:\\cookies.txt"; 
$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, $url); 
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie); 
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
$response = curl_exec($ch); 
if (curl_errno($ch)) die(curl_error($ch)); 
$dom = new DomDocument(); 
$dom->loadHTML($response); 
$tokens = $dom->getElementsByTagName("meta"); 
for ($i = 0; $i < $tokens->length; $i++) 
{ 
    $meta = $tokens->item($i); 
    if($meta->getAttribute('name') == 'csrf-token') 
    $token = $meta->getAttribute('content'); 
} 
$postinfo = "email=".$username."&password=".$password."&_csrf=".$token; 
echo $token; //debug info 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); 
curl_setopt($ch, CURLOPT_POST, true); 
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie); 
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie); 
curl_setopt($ch, CURLOPT_POSTFIELDS, $postinfo); 
$html = curl_exec($ch); 
    print($html); 
if (curl_errno($ch)) print curl_error($ch); 
    curl_close($ch); 
Смежные вопросы