首页 > 解决方案 > 需要用php和curl登录ipb板

问题描述

我正在尝试使用 CURL 和 PHP 登录 IP 板。这是我正在使用的代码。有人有想法吗?

<?php

    $url=stream_get_contents(fopen('https://invisioncommunity.com/login/', "rb"));

    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);
    }

    $csrf_key = get_string_between($url, '" value="', '">');

    $path = "/root/ctemp";

    $postinfo = "csrfKey=".$csrf_key."&auth=____USERNAME_______&password=___PASSWORD____&remember_me=1&_processLogin=usernamepassword&_processLogin=usernamepassword";
    $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);
    //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_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_REFERER, "https://invisioncommunity.com/login/");
    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);

    //page with the content I want to grab
    curl_setopt($ch, CURLOPT_URL, "https://invisioncommunity.com/discover/unread/");

    //do stuff with the info with DomDocument() etc
    $html = curl_exec($ch);

    echo $html;

    curl_close($ch);
    ?>

标签: curlipb

解决方案


是的,您的 csrf 令牌与提供给 stream_get_contents 请求的 cookie 会话相关联,没有该 cookie,您的 csrf 令牌毫无价值,而且您永远不会从 stream_get_contents 中提取 cookie(我认为 stream_get_contents 甚至不支持这样做),重写它与 curl_ api 一起使用,并确保 curl 的 cookie 系统已启用(例如,将 CURLOPT_COOKIEFILE 设置为空字符串,这将启用 libcurl 的 cookie 处理系统)。您的 csrf 提取代码也不可靠,它不会解码 html 实体(例如,如果 csrf 令牌包含一个&,它将被 html 编码为&amp;,但您的代码不会转换&amp;&. ),而是使用适当的 HTML 解析器,例如 DOMDocument。您也没有对 csrf_key 进行 urlencode,因此如果它包含特殊字符(如 @,稍后会详细介绍),它可能会再次损坏。使用 urlencode() 或 http_build_query() 正确地对 csrf 密钥、用户名和密码进行 urlencode,因为您也没有对它们进行 urlencoding。您知道@您的电子邮件中的 必须编码为%40吗?我敢打赌,当你硬编码你的登录电子邮件时,你只写foo@gmail.com,你不写foo%40gmail.com,所以你也必须对它进行 urlencode。

试试这个,使用 http_build_query 编码发布数据,并使用 DOMDocument 解析出 csrf 令牌:

<?php
declare(strict_types = 1);
$ch = curl_init ();
curl_setopt_array ( $ch, array (
        CURLOPT_COOKIEFILE => '',
        CURLOPT_ENCODING => '',
        CURLOPT_RETURNTRANSFER => 1,
        CURLOPT_FOLLOWLOCATION => 1,
        CURLOPT_URL => 'https://invisioncommunity.com/login/' 
) );
$html = curl_exec ( $ch );
$domd = @DOMDocument::loadHTML ( $html );
$xp = new DOMXPath ( $domd );
curl_setopt_array ( $ch, array (
        CURLOPT_URL => 'https://invisioncommunity.com/login/',
        CURLOPT_POST => 1,
        CURLOPT_POSTFIELDS => http_build_query ( array (
                'csrfKey' => $xp->query ( '//input[@name="csrfKey"]' )->item ( 0 )->getAttribute ( "value" ),
                'auth' => '____USERNAME_______',
                'password' => '___PASSWORD____',
                'remember_me' => 1,
                '_processLogin' => 'usernamepassword' 

        ) ) 
) );
$html = curl_exec ( $ch );
echo $html;

推荐阅读