使用 CSRF 令牌登录的 PHP cURL 不起作用 (9gag.com)


PHP cURL login with CSRF token not working (9gag.com)

好的,这是我(可能非常具有挑战性的(问题:

我正在尝试使用 PHP 和 cURL 登录 9gag.com/login,但它不起作用。没有错误或任何东西,即使响应看起来也很好。

登录表单受 CSRF 令牌保护,因此脚本首次连接以获取 cookie(会话、ts1 等(和关联的 CSRF 令牌。

之后,脚本将获得的cookie,CSRF令牌以及用户名/密码组合发布到服务器。

您可能会注意到,还会发布更多 Cookie,例如"_gat"或"__gads",但它们的值要么不会改变,要么是自我解释的(例如"国家/地区代码"(,要么仅对 Google 广告跟踪和统计目的很重要。

这两个请求与浏览器(在我的例子中为 Safari(提交它们(我使用了 Live HTTP 标头(完全相同,因此 API 根本不应该看到任何区别。

这是我的 php 片段:

$login_email = 'some_email@email.com';
$login_pass = 'some_password';
function get_string_between($string, $start, $end) {
    $string = ' ' . $string;
    $ini = strpos($string, $start);
    if ($ini == 0) return '';
    $ini += strlen($start);
    $len = strpos($string, $end, $ini) - $ini;
    return substr($string, $ini, $len);
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://9gag.com/login');
curl_setopt($ch, CURLOPT_POST, FALSE);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept-Charset: utf-8',
                                           'Accept-Language: en-us,en;q=0.7,bn-bd;q=0.3',
                                           'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'));
curl_setopt($ch, CURLOPT_COOKIEJAR, getcwd () . '/cookies_9gag.txt' );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/601.5.17 (KHTML, like Gecko) Version/9.1 Safari/601.5.17");
$gag_login_page = curl_exec($ch) or die(curl_error($ch));
$pos_csrftoken = strpos($gag_login_page, 'name="csrftoken"');
$part_csrf = substr($gag_login_page, $pos_csrftoken + 9, 100);
$gag_csrf = get_string_between($part_csrf, 'value="', '"');
preg_match_all('/^Set-Cookie:'s*([^;]*)/mi', $gag_login_page, $matches);
$cookies = array();
foreach($matches[1] as $item) {
    parse_str($item, $cookie);
    $cookies = array_merge($cookies, $cookie);
}
$phpsessid = $cookies['PHPSESSID'];
$ts1 = $cookies['ts1'];
$ri = $cookies['____ri'];
$session = $cookies['session'];
//echo 'Cookie: _gat=1;____ri='.$ri.'; ts1='.$ts1.'; sign_up_referer=https%3A%2F%2F9gag.com%2Flogin; countryCode=00; cacheableGrace=1; __gads=ID=d94815096752d058:T=1462990222:S=ALNI_Ma8SdWnOioJeYSCcIdj7p1LdHtgpA; PHPSESSID='.$phpsessid.'; session='.urlencode($session).'; gag_tz=2; _ga=GA1.2.1699141998.1462990222; _pk_id.7.f7ab=d2deed23abfae124.1462990220.1.1462990329.1462990220.; _pk_ses.7.f7ab=*';
curl_setopt($ch, CURLOPT_URL, 'https://9gag.com/login');
curl_setopt($ch, CURLOPT_POSTFIELDS,'csrftoken='.urlencode($gag_csrf).'&next='.'&location=1'.'&username='.urlencode($login_email).'&password='.urlencode($login_pass));
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept-Charset: utf-8',
                                           'Connection: keep-alive',
                                           'Accept-Language: en-us,en;q=0.7,bn-bd;q=0.3',
                                           'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                                           'Cookie: _gat=1; ____ri='.$ri.'; ts1='.$ts1.'; sign_up_referer=https%3A%2F%2F9gag.com%2Flogin; countryCode=00; cacheableGrace=1; __gads=ID=d94815096752d058:T=1462990222:S=ALNI_Ma8SdWnOioJeYSCcIdj7p1LdHtgpA; PHPSESSID='.$phpsessid.'; session='.urlencode($session).'; gag_tz=2; _ga=GA1.2.1699141998.1462990222; _pk_id.7.f7ab=d2deed23abfae124.1462990220.1.1462990329.1462990220.; _pk_ses.7.f7ab=*'
                                          )); 
curl_setopt($ch, CURLOPT_COOKIEFILE, getcwd () . '/cookies_9gag.txt' );
curl_setopt($ch, CURLOPT_COOKIEJAR, getcwd () . '/cookies_9gag.txt' );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/601.5.17 (KHTML, like Gecko) Version/9.1 Safari/601.5.17");
$gag_logged_in_page = curl_exec($ch) or die(curl_error($ch));
$pos = strpos(gag_logged_in_page, 'some_username');
if ($pos === false) {
  echo 'Not logged in.';
}
curl_close($ch);

感谢您的阅读和帮助!有好的一天!

PS:我知道从响应中获取cookie和CSRF令牌的代码可能有点不寻常,并且有更好的方法可以做到这一点,但是它正在工作(已经检查过(。

PS2:我也知道已经有一个名为Infinigag的9gag的JSON API,但它没有我需要的功能,所以我无法使用它。我已经联系了作者,但他几周来都没有回复,所以我没有机会问他是如何解决这个问题的。

如果没有启用javascript,您将无法访问9gag上的任何用户相关内容(curl 没有(,但您可以废弃任何其他页面的内容。我想他们为基于用户的操作(如投票、上传等(提供了某种javascript检测。您可以考虑用硒自动化您的请求。


注意:

我已经测试了包括您的在内的几个脚本,尽管我可以使用会话和令牌获取cookie,但在尝试访问用户相关内容时,curl 请求要么超时,要么返回