簡體   English   中英

PHP Curl請求不起作用,但在POSTMAN中工作正常

[英]PHP Curl request not working but works fine in POSTMAN

我正在嘗試登錄MCA門戶網站(POST網址: http//www.mca.gov.in/mcafoportal/loginValidateUser.do

我嘗試使用Google Chrome上的POSTMAN應用登錄,效果很好。 但是,它在PHP / Python中都不起作用。 我無法通過PHP / Python登錄

這是PHP代碼:

$url="http://www.mca.gov.in/mcafoportal/loginValidateUser.do"; 

$post_fields = array();

$post_fields['userNamedenc']='hGJfsdnk`1t';
$post_fields['passwordenc']='675894242fa9c66939d9fcf4d5c39d1830f4ddb9';
$post_fields['accessCode'] = ""

$str = call_post_mca($url, $post_fields);
$str = str_replace(" ","",$str);   

$dom = new DOMDocument();
$dom->loadHTML($str);
$xpath = new DOMXPath($dom);

$input_id =  '//input[@id="login_accessCode"]/@value';
$input_val = $xpath->query($input_id)->item(0);
$input_val1 = $input_val->nodeValue;

$url="http://www.mca.gov.in/mcafoportal/loginValidateUser.do"; 

$post_fields['userNamedenc']='hGJfsdnk`1t';
$post_fields['passwordenc']='675894242fa9c66939d9fcf4d5c39d1830f4ddb9';
$post_fields['accessCode'] = $input_val1;  //New Accesscode 

function  call_post_mca($url, $params)
{   
    #$user_agent = getRandomUserAgent();
    $user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36";
    $str = "";
    foreach($params as $key=>$value)
    {
        $str = $str . "$key=$value" . "&";
    }
    $postData = rtrim($str, "&");

    $ch = curl_init();  

    curl_setopt($ch,CURLOPT_URL,$url);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
    curl_setopt($ch,CURLOPT_HEADER, false); 
    #curl_setopt($ch, CURLOPT_CAINFO, DOC_ROOT . '/includes/cacert.pem');

    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);   


    curl_setopt($ch,CURLOPT_USERAGENT, $user_agent);
    curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt ($ch, CURLOPT_REFERER, $url); 

    $cookie= DOC_ROOT . "/cookie.txt";
    curl_setopt ($ch, CURLOPT_COOKIEJAR, $cookie); 
    curl_setopt ($ch, CURLOPT_COOKIEFILE, $cookie); 

    $output=curl_exec($ch);

    curl_close($ch);
    return $output;

}

在此輸入圖像描述

知道缺少什么嗎?

該網站進行重定向,因此您需要添加

CURLOPT_FOLLOWLOCATION => 1

到您的選項數組。 如果對cURL有疑問,請嘗試

$status = curl_getinfo($curl);
echo json_encode($status, JSON_PRETTY_PRINT);

給予:

{
"url": "http:\/\/www.mca.gov.in\/mcafoportal\/loginValidateUser.do?userNamedenc=hGJfsdnk%601t&passwordenc=675894242fa9c66939d9fcf4d5c39d1830f4ddb9&accessCode=-825374456",
"content_type": "text\/plain",
"http_code": 302,
"header_size": 1560,
"request_size": 245,
"filetime": -1,
"ssl_verify_result": 0,
"redirect_count": 0,
"total_time": 1.298891,
"namelookup_time": 0.526375,
"connect_time": 0.999786,
"pretransfer_time": 0.999844,
"size_upload": 0,
"size_download": 0,
"speed_download": 0,
"speed_upload": 0,
"download_content_length": 0,
"upload_content_length": -1,
"starttransfer_time": 1.298875,
"redirect_time": 0,
"redirect_url": "http:\/\/www.mca.gov.in\/mcafoportal\/login.do",
"primary_ip": "115.114.108.120",
"certinfo": [],
"primary_port": 80,
"local_ip": "192.168.1.54",
"local_port": 62524
}

如您所見,您獲得了302重定向狀態,但redirect_count0 添加選項后,我得到:

{
"url": "http:\/\/www.mca.gov.in\/mcafoportal\/login.do",
"content_type": "text\/html;charset=ISO-8859-1",
"http_code": 200,
"header_size": 3131,
"request_size": 376,
"filetime": -1,
"ssl_verify_result": 0,
"redirect_count": 1,
"total_time": 2.383609,
"namelookup_time": 1.7e-5,
"connect_time": 1.7e-5,
"pretransfer_time": 4.4e-5,
"size_upload": 0,
"size_download": 42380,
"speed_download": 17779,
"speed_upload": 0,
"download_content_length": 42380,
"upload_content_length": -1,
"starttransfer_time": 0.30734,
"redirect_time": 0.915858,
"redirect_url": "",
"primary_ip": "14.140.191.120",
"certinfo": [],
"primary_port": 80,
"local_ip": "192.168.1.54",
"local_port": 62642
}

EDIT url對請求參數進行編碼,並遵循重定向

 $str = urlencode("userNamedenc=hGJfsdnk%601t&passwordenc=675894242fa9c66939d9fcf4d5c39d1830f4ddb9&accessCode=-825374456");
curl_setopt_array(
    $curl , array (
    CURLOPT_URL            => "http://www.mca.gov.in/mcafoportal/loginValidateUser.do" , // <- removed parameters here
    CURLOPT_RETURNTRANSFER => true ,
    CURLOPT_ENCODING       => "" ,
    CURLOPT_FOLLOWLOCATION => 1 ,
    CURLOPT_MAXREDIRS      => 10 ,
    CURLOPT_TIMEOUT        => 30 ,
    CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1 ,
    CURLOPT_CUSTOMREQUEST  => "POST" ,
    CURLOPT_POSTFIELDS     => $str,       // <- added this here
    CURLOPT_HTTPHEADER     => array (
        "cache-control: no-cache"
    ) ,
)
);

通過代碼成功登錄

老實說,這是我很久以來見過的一個奇怪的網站。 首先要知道它是如何工作的。 所以我決定使用chrome,看看當我們使用錯誤的數據登錄時會發生什么

現場

觀察:

  • 空白用戶名和密碼字段
  • 生成用戶名和密碼字段的SHA1哈希值,然后respectivelyuserNamedenc設置
  • 我們可以直接在JavaScript中覆蓋用戶名和密碼,只需從控制台覆蓋詳細信息即可登錄您的帳戶。
  • 生成cookie有很多不同的請求,但沒有一個看起來有用

因此,解決問題的方法是遵循以下步驟

  • 獲取登錄URL login.do
  • 從訪問代碼的響應中獲取表單詳細信息
  • 將表單提交到loginValidateUser.do

表單發送以下參數

表格提交

現在,一個有趣的部分是在發布數據之下

displayCaptcha:true
userEnteredCaptcha:strrty

如果我們將displayCaptcha覆蓋為false,則不再需要驗證碼。 這是一次精彩的繞行

displayCaptcha: false

接下來是在PHP中對上述所有內容進行編碼,但該網站似乎很奇怪,許多嘗試都失敗了。 所以最后我意識到我們需要更接近瀏覽器登錄,而且我覺得需要延遲調用

<?php

    require_once("curl.php");

    $curl = new CURL();
    $default_headers = Array(
        "Accept" => "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "Accept-Encoding" => "deflate",
        "Accept-Language" => "en-US,en;q=0.8",
        "Cache-Control" => "no-cache",
        "Connection" => "keep-alive",
        "DNT" => "1",
        "Pragma" => "no-cache",
        "Referer" => "http://www.mca.gov.in/mcafoportal/login.do",
        "Upgrade-Insecure-Requests" => "1"
    );

    // Get the login page 
    $curl
        ->followlocation(0)
        ->cookieejar("")
        ->verbose(1)
        ->get("http://www.mca.gov.in/mcafoportal/login.do")
        ->header($default_headers)
        ->useragent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36")
        ->execute();


    // Save the postfileds and access code as we would need them later for the POST field
    $post = $curl->loadInputFieldsFromResponse()
        ->updatePostParameter(array(
            "displayCaptcha" => "false",
            "userNamedenc" => "hGJfsdnk`1t",
            "passwordenc" => "675894242fa9c66939d9fcf4d5c39d1830f4ddb9",
            "userName" => "",
            "Cert" => ""))
        ->referrer("http://www.mca.gov.in/mcafoportal/login.do")
        ->removePostParameters(
            Array("dscBasedLoginFlag", "maxresults", "fe", "query", "SelectCert", "newUserRegistration")
        );

    $postfields = $curl->getPostFields();

    var_dump($postfields);


    // Access some dummy URLs to make it look like browser
    $curl
        ->get("http://www.mca.gov.in/mcafoportal/js/global.js")->header($default_headers)->execute()->sleep(2)
        ->get("http://www.mca.gov.in/mcafoportal/js/loginValidations.js")->header($default_headers)->execute()->sleep(2)
        ->get("http://www.mca.gov.in/mcafoportal/css/layout.css")->header($default_headers)->execute()->sleep(2)
        ->get("http://www.mca.gov.in/mcafoportal/img/bullet.png")->header($default_headers)->execute()->sleep(2)
        ->get("http://www.mca.gov.in/mcafoportal/getCapchaImage.do")->header($default_headers)->execute()->sleep(2);


    // POST to the login form the postfields saved earlier
    $curl
        ->sleep(20)
        ->header($default_headers)
        ->postfield($postfields)
        ->referrer("http://www.mca.gov.in/mcafoportal/login.do")
        ->post("http://www.mca.gov.in/mcafoportal/loginValidateUser.do")
        ->execute(false)
        ->sleep(3)
        ->get("http://www.mca.gov.in/mcafoportal/login.do")
        ->header($default_headers)
        ->execute(true);

    // Get the response from last GET of login.do
    $curl->getResponseText($output);

    //Check if user name is present in the output or not
    if (stripos($output, "Kiran") > 0) {
        echo "Hurray!!!! Login succeeded";
    } else {
        echo "Login failed please retry after sometime";
    }

運行代碼后,它可以運行幾次,而不會運行幾次。 我的觀察

  • 一次只允許一次登錄。 所以不確定其他人是否在我測試時使用登錄
  • 沒有延遲,大多數時間都會失敗
  • 除了站點在服務器端執行某些操作以阻止請求之外,沒有明顯的原因

成功登錄

我創建並用於鏈接方法的可重用curl.php如下

<?php

class CURL
{
    protected $ch;
    protected $postfields;

    public function getPostFields() {
        return $this->postfields;
    }

    public function newpost()
    {
        $this->postfields = array();
        return $this;
    }

    public function addPostFields($key, $value)
    {
        $this->postfields[$key]=$value;
        return $this;
    }

    public function __construct()
    {
        $ch       = curl_init();
        $this->ch = $ch;
        $this->get()->followlocation()->retuntransfer(); //->connectiontimeout(20)->timeout(10);
    }

    function url($url)
    {
        curl_setopt($this->ch, CURLOPT_URL, $url);
        return $this;
    }

    function verbose($value = true)
    {
        curl_setopt($this->ch, CURLOPT_VERBOSE, $value);
        return $this;
    }

    function post($url='')
    {
        if ($url !== '')
            $this->url($url);
        curl_setopt($this->ch, CURLOPT_POST, count($this->postfields));
        curl_setopt($this->ch, CURLOPT_POSTFIELDS, http_build_query($this->postfields));
        return $this;
    }

    function postfield($fields)
    {
        if (is_array($fields)){
            $this->postfields = $fields;
        }
        return $this;
    }

    function close()
    {
        curl_close($this->ch);
        return $this;
    }

    function cookieejar($cjar)
    {
        curl_setopt($this->ch, CURLOPT_COOKIEJAR, $cjar);
        return $this;
    }

    function cookieefile($cfile)
    {
        curl_setopt($this->ch, CURLOPT_COOKIEFILE, $cfile);
        return $this;
    }

    function followlocation($follow = 1)
    {
        curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, $follow);
        return $this;
    }

    function loadInputFieldsFromResponse($response ='')
    {
        if ($response)
            $doc = $response;
        else
            $doc = $this->lastCurlRes;


        /* @var $doc DOMDocument */
        //simplexml_load_string($data)
        $this->getResponseDoc($doc);
        $this->postfields = array();

        foreach ($doc->getElementsByTagName('input') as $elem) {
            /* @var $elem DomNode */
            $name = $elem->getAttribute('name');
//            if (!$name)
//                $name = $elem->getAttribute('id');
            if ($name)
                $this->postfields[$name] = $elem->getAttribute("value");

        }

        return $this;
    }

    function retuntransfer($transfer=1)
    {
        curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, $transfer);
        return $this;
    }

    function connectiontimeout($connectiontimeout)
    {
        curl_setopt($this->ch, CURLOPT_CONNECTTIMEOUT, $connectiontimeout);
        return $this;
    }

    function timeout($timeout)
    {
        curl_setopt($this->ch, CURLOPT_TIMEOUT, $timeout);
        return $this;
    }
    function useragent($useragent)
    {
        curl_setopt($this->ch, CURLOPT_USERAGENT, $useragent);
        return $this;
    }

    function referrer($referrer)
    {
        curl_setopt($this->ch, CURLOPT_REFERER, $referrer);
        return $this;
    }

    function getCURL()
    {
        return $this->ch;
    }

    protected $lastCurlRes;
    protected $lastCurlResInfo;

    function get($url = '')
    {
        if ($url !== '')
            $this->url($url);
        curl_setopt($this->ch, CURLOPT_POST, 0);
        curl_setopt($this->ch, CURLOPT_HTTPGET, true);
        return $this;
    }

    function sleep($seconds){
        sleep($seconds);
        return $this;
    }

    function execute($output=false)
    {
        $this->lastCurlRes = curl_exec($this->ch);

        if ($output == true)
        {
            echo "Response is \n " . $this->lastCurlRes;
            file_put_contents("out.html", $this->lastCurlRes);
        }
        $this->lastCurlResInfo = curl_getinfo($this->ch);
        $this->postfields = array();
        return $this;
    }

    function header($headers)
    {
        //curl_setopt($this->ch, CURLOPT_HEADER, true);
        curl_setopt($this->ch, CURLOPT_HTTPHEADER, $headers);
        return $this;
    }
    function getResponseText(&$text){
        $text = $this->lastCurlRes;
        return $this;
    }


    /*
     *
    * @param DOMDocument $doc
    *
    *
    */
    function getResponseDoc(&$doc){
        $doc = new DOMDocument();
        libxml_use_internal_errors(false);
        libxml_disable_entity_loader();
        @$doc->loadHTML($this->lastCurlRes);
        return $this;
    }

    function removePostParameters($keys) {
        if (!is_array($keys))
            $keys = Array($keys);

        foreach ($keys as $key){
            if (array_key_exists($key, $this->postfields))
                unset($this->postfields[$key]);
        }

        return $this;
    }

    function keepPostParameters($keys) {
        $delete = Array();
        foreach ($this->postfields as $key=>$value){
            if (!in_array($key, $keys)){
                array_push($delete, $key);
            }
        }

        foreach ($delete as $key) {
            unset($this->postfields[$key]);
        }

        return $this;
    }

    function updatePostParameter($postarray, $encoded=false)
    {
        if (is_array($postarray))
        {
            foreach ($postarray as $key => $value) {
                if (is_null($value))
                    unset($this->postfields[$key]);
                else
                    $this->postfields[$key] = $value;
            }}
        elseif (is_string($postarray))
        {
            $parr = preg_split("/&/",$postarray);
            foreach ($parr as $postvalue) {
                if (($index = strpos($postvalue, "=")) != false)
                {
                    $key = substr($postvalue, 0,$index);
                    $value = substr($postvalue, $index + 1);
                    if ($encoded)
                        $this->postfields[$key]=urldecode($value);
                    else
                        $this->postfields[$key]=$value;
                }
                else
                    $this->postfields[$postvalue] = "";
            }


        }

        return $this;
    }

    function getResponseXml(){
        //SimpleXMLElement('<INPUT/>')->asXML();
    }

    function SSLVerifyPeer($verify=false)
    {
        curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, $verify);
        return $this;
    }
}

?>

@yvesleborg和@ tarun-lalwani給出了正確的提示。 您需要處理cookie和重定向。 但是,它總是不適合我。 我想站點運營商要求兩個請求之間有一些超時。

我重新編寫了一些代碼來玩它。 mycurl.php:

function my_curl_init() {
    $url="http://www.mca.gov.in/mcafoportal/loginValidateUser.do"; 
    $user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36";

    $ch = curl_init();  

    curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    return $ch;
}

/*
 * first call in order to get accessCode and sessionCookie
 */
$ch = my_curl_init();
curl_setopt($ch, CURLOPT_COOKIEJAR, __DIR__ . "/cookie.txt"); // else cookielist is empty

$output = curl_exec($ch);

file_put_contents(__DIR__ . '/loginValidateUser.html', $output);

// save cookie info
$cookielist = curl_getinfo($ch, CURLINFO_COOKIELIST);
//print_r($cookielist);

curl_close($ch);

// parse accessCode from output
$re = '/\<input.*name="accessCode".*value="([-0-9]+)"/';
preg_match_all($re, $output, $matches, PREG_SET_ORDER, 0);
if ($matches) {
    $accessCode = $matches[0][1];

    // debug
    echo "accessCode: $accessCode" . PHP_EOL;   


    /*
     * second call in order to login
     */ 

    $post_fields = array(
        'userNamedenc' => 'hGJfsdnk`1t',
        'passwordenc'  => '675894242fa9c66939d9fcf4d5c39d1830f4ddb9',
        'accessCode'   => $accessCode
    );

    $cookiedata = preg_split('/\s+/', $cookielist[0]);
    $session_cookie = $cookiedata[5] . '=' . $cookiedata[6];

    // debug
    echo "sessionCookie: $session_cookie" . PHP_EOL;
    file_put_contents(__DIR__ . '/cookie2.txt', $session_cookie);

    /* 
     * !!! pause !!!
     */  
    sleep(20);

    // debug
    echo "curl -v -L -X POST -b '$session_cookie;' --data 'userNamedenc=hGJfsdnk`1t&passwordenc=675894242fa9c66939d9fcf4d5c39d1830f4ddb9&accessCode=$accessCode' http://www.mca.gov.in/mcafoportal/loginValidateUser.do > loginValidateUser2.html";

    $ch = my_curl_init();  

    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);   

    curl_setopt($ch, CURLOPT_COOKIE, $session_cookie);

    $output = curl_exec($ch);

    file_put_contents(__DIR__ . '/loginValidateUser2.html', $output);

    curl_close($ch);
}

該腳本向網站發出兩個請求。 第一個的輸出用於讀取accessCode並存儲會話cookie。 然后在稍微休息之后,使用accessCode和會話信息以及登錄憑證發布第二個。

我從終端( php -f mycurl.php )用PHP5.6測試了它。 該腳本調試所有必要的信息,輸出您可以在終端中使用的curl命令,並將HTML和cookie信息記錄到腳本所在的同一文件夾中的某些文件中。

經常運行腳本不起作用。 登錄無效。 因此,請花時間在嘗試之間等待幾分鍾。 或者更改您的IP;)

希望能幫助到你。

復制問題

我在Postman做了同樣的事情,就像截圖一樣,但無法登錄:

在此輸入圖像描述

我能看到的唯一區別是你的請求有cookie,我懷疑這是你能夠在沒有所有其他輸入字段的情況下登錄的原因。 似乎有很多輸入字段:

在此輸入圖像描述

使用郵遞員

所以,我使用postman攔截來捕獲登錄期間使用的所有字段,包括驗證碼和訪問代碼,我能夠登錄:

在此輸入圖像描述

更新1

我發現一旦你解決了驗證密碼登錄,你注銷后你可以再次登錄你的表單數據中沒有displayCaptchauserEnteredCaptcha前提是你使用的cookie與你曾經使用過的cookie相同登錄成功。 您只需從登錄頁面獲取有效的accessCode

it doesnt work either in PHP/Python中都it doesnt work either in PHP/Python (正如其他人已經指出的那樣),因為你使用的瀏覽器現有的cookie會話已經解決了驗證碼。 清除您的瀏覽器cookie,獲得一個新的cookie會話,並且不要解決CAPTCHA,Postman也將無法登錄。 Any idea what is missing ? 幾件事,其中包括幾個帖子登錄參數( browserFlagloginType__checkbox_dscBasedLoginFlag等等),你的編碼循環也是錯誤的$str = $str . "$key=$value" . "&"; $str = $str . "$key=$value" . "&"; ,只要密鑰和值都只包含[a-zA-Z0-9]字符,它幾乎只能工作,並且由於你的userNamedenc包含一個嚴重的重音字符,你的編碼循環是不夠的。 一個固定的循環

foreach($params as $key=>$value){
    $str = $str . urlencode($key)."=".urlencode($value) . "&";
}
$str=substr($str,0,-1);

,但這正是為什么我們有http_build_query函數,整個循環和以下修剪可以替換為這一行:

$str=http_build_query($params);

而且,似乎你試圖在沒有預先存在的cookie會話的情況下登錄,這不會起作用。 當您對登錄頁面發出GET請求時,會得到一個cookie和一個唯一的驗證碼,驗證碼答案與您的cookie會話相關聯,需要在您嘗試登錄之前解決,您也沒有提供任何代碼來處理驗證碼。 另外,在解析“userName”輸入元素時,它將默認為“輸入用戶名”,用javascript清空並替換為userNamedenc,你必須在PHP中復制它,它還有一個名為“dscBasedLoginFlag”的輸入元素,用javascript刪除,你也必須在php中做這個部分,它也有一個名為“Cert”的輸入元素,它有一個默認值,但這個值用javascript清除,在php中做同樣的事,輸入元素命名為“newUserRegistration”,用javascript刪除,這樣做,

這是你應該做的:向登錄頁面發出GET請求,保存cookie會話並確保為所有進一步的請求提供它,並解析所有登錄表單的元素並將它們添加到您的登錄請求中(但要小心,有2x表單輸入,1個屬於搜索欄,只解析登錄表單的子項,不要混合2 ),並記得清除/刪除特殊輸入標簽來模擬javascript,如上所述,然后向驗證碼網址發出GET請求,確保提供會話cookie,解決驗證碼,然后使用驗證碼答案,userNamedenc和passwordenc以及從登錄頁面解析出的所有其他元素,發出最終登錄請求。那應該有用。 現在,以編程方式解決驗證碼,captha看起來並不太難,破解它可能是自動化的,但是直到某人真的這樣做,你可以使用Deathbycaptcha為你做,但請注意它不是免費服務。

這是一個經過全面測試的工作示例實現,使用我的hhb_curl庫(來自https://github.com/divinity76/hhb_.inc.php/blob/master/hhb_.inc.php )和Deathbycaptcha api:

<?php
declare(strict_types = 1);
header ( "content-type: text/plain;charset=utf8" );
require_once ('hhb_.inc.php');
const DEATHBYCATPCHA_USERNAME = '?';
const DEATHBYCAPTCHA_PASSWORD = '?';
$hc = new hhb_curl ( '', true );
$hc->setopt(CURLOPT_TIMEOUT,20);// im on a really slow net atm :(
$html = $hc->exec ( 'http://www.mca.gov.in/mcafoportal/login.do' )->getResponseBody (); // cookie session etc
$domd = @DOMDocument::loadHTML ( $html );
$inputs = getDOMDocumentFormInputs ( $domd, true ) ['login'];
$params = [ ];
foreach ( $inputs as $tmp ) {
    $params [$tmp->getAttribute ( "name" )] = $tmp->getAttribute ( "value" );
}
assert ( isset ( $params ['userNamedenc'] ), 'username input not found??' );
assert ( isset ( $params ['passwordenc'] ), 'passwordenc input not found??' );
$params ['userName'] = ''; // defaults to "Enter Username", cleared with javascript
unset ( $params ['dscBasedLoginFlag'] ); // removed with javascript
$params ['Cert'] = ''; // cleared to emptystring with javascript
unset ( $params ['newUserRegistration'] ); // removed with javascript
unset ( $params ['SelectCert'] ); // removed with javascript
$params ['userNamedenc'] = 'hGJfsdnk`1t';
$params ['passwordenc'] = '675894242fa9c66939d9fcf4d5c39d1830f4ddb9';
echo 'parsed login parameters: ';
var_dump ( $params );
$captchaRaw = $hc->exec ( 'http://www.mca.gov.in/mcafoportal/getCapchaImage.do' )->getResponseBody ();
$params ['userEnteredCaptcha'] = solve_captcha2 ( $captchaRaw );
// now actually logging in.
$html = $hc->setopt_array ( array (
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => http_build_query ( $params ) 
) )->exec ( 'http://www.mca.gov.in/mcafoportal/loginValidateUser.do' )->getResponseBody ();
var_dump ( $hc->getStdErr (), $hc->getStdOut () ); // printing debug data
$domd = @DOMDocument::loadHTML ( $html );
$xp = new DOMXPath ( $domd );
$loginErrors = $xp->query ( '//ul[@class="errorMessage"]' );
if ($loginErrors->length > 0) {
    echo 'encountered following error(s) logging in: ';
    foreach ( $loginErrors as $err ) {
        echo $err->textContent, PHP_EOL;
    }
    die ();
}
echo "logged in successfully!";
/**
 * solves the captcha manually, by doing: echo ANSWER>captcha.txt
 *
 * @param string $raw_image
 *          raw image bytes
 * @return string answer
 */
function solve_captcha2(string $raw_image): string {
    $imagepath = getcwd () . DIRECTORY_SEPARATOR . 'captcha.png';
    $answerpath = getcwd () . DIRECTORY_SEPARATOR . 'captcha.txt';
    @unlink ( $imagepath );
    @unlink ( 'captcha.txt' );
    file_put_contents ( $imagepath, $raw_image );
    echo 'the captcha is saved in ' . $imagepath . PHP_EOL;
    echo ' waiting for you to solve it by doing: echo ANSWER>' . $answerpath, PHP_EOL;
    while ( true ) {
        sleep ( 1 );
        if (file_exists ( $answerpath )) {
            $answer = trim ( file_get_contents ( $answerpath ) );
            echo 'solved: ' . $answer, PHP_EOL;
            return $answer;
        }
    }
}
function solve_captcha(string $raw_image): string {
    echo 'solving captcha, hang on, with DEATBYCAPTCHA this usually takes between 10 and 20 seconds.';
    {
        // unfortunately, CURLFile requires a filename, it wont accept a string, so make a file of it
        $tmpfileh = tmpfile ();
        fwrite ( $tmpfileh, $raw_image ); // TODO: error checking (incomplete write or whatever)
        $tmpfile = stream_get_meta_data ( $tmpfileh ) ['uri'];
    }
    $hc = new hhb_curl ( '', true );
    $hc->setopt_array ( array (
            CURLOPT_URL => 'http://api.dbcapi.me/api/captcha',
            CURLOPT_POSTFIELDS => array (
                    'username' => DEATHBYCATPCHA_USERNAME,
                    'password' => DEATHBYCAPTCHA_PASSWORD,
                    'captchafile' => new CURLFile ( $tmpfile, 'image/png', 'captcha.png' ) 
            ) 
    ) )->exec ();
    fclose ( $tmpfileh ); // when tmpfile() is fclosed(), its also implicitly deleted.
    $statusurl = $hc->getinfo ( CURLINFO_EFFECTIVE_URL ); // status url is given in a http 300x redirect, which hhb_curl auto-follows
    while ( true ) {
        // wait for captcha to be solved.
        sleep ( 10 );
        echo '.';
        $json = $hc->setopt_array ( array (
                CURLOPT_HTTPHEADER => array (
                        'Accept: application/json' 
                ),
                CURLOPT_HTTPGET => true 
        ) )->exec ()->getResponseBody ();
        $parsed = json_decode ( $json, false );
        if (! empty ( $parsed->captcha )) {
            echo 'captcha solved!: ' . $parsed->captcha, PHP_EOL;
            return $parsed->captcha;
        }
    }
}
function getDOMDocumentFormInputs(\DOMDocument $domd, bool $getOnlyFirstMatches = false): array {
    // :DOMNodeList?
    $forms = $domd->getElementsByTagName ( 'form' );
    $parsedForms = array ();
    $isDescendantOf = function (\DOMNode $decendant, \DOMNode $ele): bool {
        $parent = $decendant;
        while ( NULL !== ($parent = $parent->parentNode) ) {
            if ($parent === $ele) {
                return true;
            }
        }
        return false;
    };
    // i can't use array_merge on DOMNodeLists :(
    $merged = function () use (&$domd): array {
        $ret = array ();
        foreach ( $domd->getElementsByTagName ( "input" ) as $input ) {
            $ret [] = $input;
        }
        foreach ( $domd->getElementsByTagName ( "textarea" ) as $textarea ) {
            $ret [] = $textarea;
        }
        foreach ( $domd->getElementsByTagName ( "button" ) as $button ) {
            $ret [] = $button;
        }
        return $ret;
    };
    $merged = $merged ();
    foreach ( $forms as $form ) {
        $inputs = function () use (&$domd, &$form, &$isDescendantOf, &$merged): array {
            $ret = array ();
            foreach ( $merged as $input ) {
                // hhb_var_dump ( $input->getAttribute ( "name" ), $input->getAttribute ( "id" ) );
                if ($input->hasAttribute ( "disabled" )) {
                    // ignore disabled elements?
                    continue;
                }
                $name = $input->getAttribute ( "name" );
                if ($name === '') {
                    // echo "inputs with no name are ignored when submitted by mainstream browsers (presumably because of specs)... follow suite?", PHP_EOL;
                    continue;
                }
                if (! $isDescendantOf ( $input, $form ) && $form->getAttribute ( "id" ) !== '' && $input->getAttribute ( "form" ) !== $form->getAttribute ( "id" )) {
                    // echo "this input does not belong to this form.", PHP_EOL;
                    continue;
                }
                if (! array_key_exists ( $name, $ret )) {
                    $ret [$name] = array (
                            $input 
                    );
                } else {
                    $ret [$name] [] = $input;
                }
            }
            return $ret;
        };
        $inputs = $inputs (); // sorry about that, Eclipse gets unstable on IIFE syntax.
        $hasName = true;
        $name = $form->getAttribute ( "id" );
        if ($name === '') {
            $name = $form->getAttribute ( "name" );
            if ($name === '') {
                $hasName = false;
            }
        }
        if (! $hasName) {
            $parsedForms [] = array (
                    $inputs 
            );
        } else {
            if (! array_key_exists ( $name, $parsedForms )) {
                $parsedForms [$name] = array (
                        $inputs 
                );
            } else {
                $parsedForms [$name] [] = $tmp;
            }
        }
    }
    unset ( $form, $tmp, $hasName, $name, $i, $input );
    if ($getOnlyFirstMatches) {
        foreach ( $parsedForms as $key => $val ) {
            $parsedForms [$key] = $val [0];
        }
        unset ( $key, $val );
        foreach ( $parsedForms as $key1 => $val1 ) {
            foreach ( $val1 as $key2 => $val2 ) {
                $parsedForms [$key1] [$key2] = $val2 [0];
            }
        }
    }
    return $parsedForms;
}

示例用法:在終端中,寫php foo.php | tee test.html php foo.php | tee test.html ,幾秒鍾之后它會說:

the captcha is saved in /home/captcha.png
 waiting for you to solve it by doing: echo ANSWER>/home/captcha.txt

然后查看/home/captcha.png中的驗證碼,解決它,並在另一個終端寫入: echo ANSWER>/home/captcha.txt ,現在腳本將登錄,並將登錄的html轉儲到test.html中,您可以在瀏覽器中打開,確認它實際登錄,運行時截圖: https//image.prntscr.com/image/_AsB_0J6TLOFSZuvQdjyNg.png

另請注意,我制作了2個驗證碼解算器函數,1個使用deathbycaptcha api,直到你在第5行和第6行提供有效且有信譽的deathbycaptcha帳戶,這不是免費的,其他1,solve_captcha2,要求你解決自己驗證,告訴你驗證驗證碼圖像的位置(這樣你就可以看看它),以及要寫入的命令行參數,以便為它提供答案。 只需用第28行的solve_captcha2替換solve_captcha ,手動解決,反之亦然。 使用solve_captcha2對腳本進行了全面測試,但是deadbycaptcha解算器未經測試,因為我的deathbycatpcha帳戶是空的(如果你想捐款,所以我可以實際測試它,發送7美元到paypal帳戶divinity76@gmail.com與鏈接到這個線程,我將購買最便宜的deathbycaptcha信用包,並實際測試它)

  • 免責聲明:我不會以任何方式與deathbycaptcha聯系(除了我幾年前他們是他們的客戶),這篇文章沒有贊助。

你可以做的最簡單的事情,就是你已經在POSTMAN中使用它,就是在POSTMAN中渲染PHP代碼。 是從POSTMAN獲取PHP代碼的鏈接。 然后,您可以將POSTMAN示例與代碼進行比較。

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "http://www.mca.gov.in/mcafoportal/loginValidateUser.do?userNamedenc=hGJfsdnk%601t&passwordenc=675894242fa9c66939d9fcf4d5c39d1830f4ddb9&accessCode=",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_HTTPHEADER => array(
    "cache-control: no-cache",
    "postman-token: b54abdc0-17be-f38f-9aba-dbf8f007de99"
  ),
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

立刻突然出現的是'hGJfsdnk`1t'。 向后引用可以是轉義字符'''。 這很可能會引發錯誤,錯誤處理會重定向回登錄頁面。 POSTMAN可能內置了一些東西來將轉義字符渲染為'hGJfsdnk%601t'。 因此,這適用於POSTMAN,但不適用於您的代碼。

以下是此請求的狀態:

{
"url": "http:\/\/www.mca.gov.in\/mcafoportal\/login.do",
"content_type": "text\/html;charset=ISO-8859-1",
"http_code": 200,
"header_size": 3020,
"request_size": 821,
"filetime": -1,
"ssl_verify_result": 0,
"redirect_count": 1,
"total_time": 2.920125,
"namelookup_time": 8.2e-5,
"connect_time": 8.7e-5,
"pretransfer_time": 0.000181,
"size_upload": 0,
"size_download": 42381,
"speed_download": 14513,
"speed_upload": 0,
"download_content_length": -1,
"upload_content_length": -1,
"starttransfer_time": 0.320995,
"redirect_time": 2.084554,
"redirect_url": "",
"primary_ip": "115.114.108.120",
"certinfo": [],
"primary_port": 80,
"local_ip": "192.168.1.3",
"local_port": 45086
}

這是顯示成功登錄。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM