在特定网站上使用验证码进行PHP卷曲登录失败

时间:2017-07-23 12:54:49

标签: php curl

我正在尝试使用curl登录licindia。但是失败了同样的代码正在其他网站上工作。 我使用了一个用于dom操作的库“simple_html_dom.php”。 网站:http://sourceforge.net/projects/simplehtmldom/ 我能够获得验证码,但在提交后它给了我“错误:Pl检查你的答案......” Cookie设置正确。

    <?php
    require_once './simple_html_dom.php';

    $host = 'customer.onlinelic.in';

    $home_url  = 'https://' . $host . '/';
    $login_url = $home_url . 'LICEPS/Login/begin.do';

    $user_agent = 'Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0';

    $headers[] = "Host: $host";
    $headers[] = "Connection: Keep-Alive";
    $headers[] = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
    $headers[] = "Host:customer.onlinelic.in";
    $headers[] = "Accept-Language:en-US,en;q=0.5";
    $headers[] = "Content-Type:application/x-www-form-urlencoded";


    $cookie  = 'cookie.txt';

    function getAnswer() {
        global $login_url, $headers, $cookie;

        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $login_url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
        curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

        $response = curl_exec($ch);

        curl_close($ch);

        $html  = str_get_html($response);
        $token = $html->find('form[name="chkLoginForm"] span', 3);

        return $token;
    }

    function login() {
        global $login_url, $headers, $cookie;

        $postFiels = [
            '{actionForm.userName}' => '12349743554',
            '{actionForm.password}' => 'dfdfg56',
            '{actionForm.qreply}' => ($_POST['ans'])
        ];

        $ch       = curl_init();
        $url      = "https://customer.onlinelic.in/LICEPS/Login/secureLogin.do";
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_REFERER, $login_url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postFiels));

        curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
        curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        $response = curl_exec($ch);

        curl_close($ch);

        echo $response;
    }
    ?>

    <html>
        <head>
            <title>Login Page</title>
        </head>
        <body>
            <form action="" method="post">
                <p><?php echo getAnswer(); ?></p>
                <input type="text" name="ans" value="<?php echo isset($_POST['ans']) ? $_POST['ans'] : ''; ?>" /><br />
                <button type="submit" name="submit">Submit</button>
            </form>

            <?php
            if (isset($_POST['submit'])) {
                login();
            }
            ?>
        </body>
    </html>

1 个答案:

答案 0 :(得分:1)

首先,没有必要使用simple_html_dom,php的内置DOMDocument&amp; DOMXpath完全有能力做到这一点,对XPath的了解很少,我建议你稍微研究一下XPaths(例如,$token = $html->find('form[name="chkLoginForm"] span', 3);可能转换为$token=$xp->query('//form[@name="chkLoginForm"]')->item(3)->textContent;

第二,不要这样做$headers[] = "Host: $host"; - curl会自动提供主机头。 (就我所能想到的那样,你想要手动提供主机头的唯一情况是你与不正确配置DNS的服务器进行通信,这是一个非常罕见的事件)

第三,你实际上并没有告诉curl使用你的用户代理字符串,将$ user_agent变量添加到CURLOPT_USERAGENT。

第四,你给主机头2次,这没有多大意义,可能是一个错误(如上所述,你应该实际提供零次,因为卷曲也会如果你没有自动为你做。)

第五,不要手动提供此标题Content-Type:application/x-www-form-urlencoded - curl会自动检测您何时使用此编码类型,并为您发送相应的标题 - 与您不同,curl赢了&#这样做可以做任何拼写错误。 (对于multipart/form-data - 编码btw)

也是如此

除此之外,你真正的问题是你的帖子字段毫无意义,他们的登录请求看起来并不像那样。您尝试以application/x-www-form-urlencoded编码发送用户名/密码,但他们真正使用的是application/json编码。您尝试在名为{actionForm.userName}的变量中发送登录用户名,但用户名的变量实际上称为userId。您尝试在名为{actionForm.password}的变量中发送密码,并尝试将其发送为原始密码,但密码实际上是在一个名为password的变量中,并且它不是原始发送的,它是第一个哈希&amp;腌制(我不确定他们使用什么哈希,但候选人是sha2-512sha3-512whirlpool,他们正在使用此库进行哈希:{{3再次进行十六进制编码后,再进行十六进制编码,再进行base64编码。 (显然网络开发人员不知道他们正在做什么,因为双重编码只是浪费cpu,ram和带宽,无论是服务器还是客户端登录。他们可以节省50%通过取消十六进制编码来获取带宽,还将登录表单作为名为userRole的变量(似乎是硬编码到Customer),以及一个名为dob的变量,它是ISO8601的时间戳{ {1}},作为登录表单问你的问题,硬编码的时间是the day you were born ...

如果您当前的代码曾经工作,他们最近必须重新设计他们的登录系统。

你需要做的第一件事就是找出他们正在使用的哈希值,然后找出给出盐的位置,然后重新实现盐和盐。 php中的哈希机制,你必须得到一个会话cookie&amp; salt在发送登录请求之前,并且...使用正确的编码(也就是使用json_encode())将正确的变量发送到T00:00:00

它变得不容易,我无法为你进一步挖掘(除非你愿意为此付钱)