La solicitud de PHP Curl no funciona pero funciona bien en POSTMAN

Estoy intentando iniciar sesión en el portal de MCA (POST URL: http://www.mca.gov.in/mcafoportal/loginValidateUser.do )

Intenté iniciar sesión con la aplicación POSTMAN en Google Chrome, que funciona bien. Sin embargo, tampoco funciona en PHP / Python. No puedo iniciar sesión a través de PHP / Python

Aquí está el código 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; } 

introduzca la descripción de la imagen aquí

¿Alguna idea de lo que falta?

Inicio de sesión exitoso a través del código

Sinceramente, este es uno de los sitios extraños que he visto en mucho tiempo. Lo primero era saber cómo funciona. Así que decidí usar Chrome y ver qué pasa cuando iniciamos sesión con datos incorrectos.

Sitio

Observaciones:

  • Espacios de usuario y contraseñas en blanco
  • Genera hash SHA1 de los campos de nombre de usuario y contraseña y los establece luego en userNamedenc y respectively
  • Podemos anular el nombre de usuario y la contraseña directamente en JavaScript e iniciar sesión en su cuenta con solo anular los detalles de la consola.
  • Hay muchas solicitudes diferentes que generan cookies, pero ninguna de ellas parece útil.

Así que el enfoque para resolver el problema era seguir los pasos a continuación.

  • Obtener el inicio de sesión url login.do
  • Obtenga los detalles del formulario de la respuesta para el código de acceso
  • Envíe el formulario para loginValidateUser.do

El formulario envía los siguientes parámetros.

Formulario de presentación

Ahora una parte interesante de la misma se encuentra debajo de los datos del post

 displayCaptcha:true userEnteredCaptcha:strrty 

Si cambiamos el displayCaptcha de displayCaptcha a falso, no se necesita más el captcha. Así que un maravilloso bypass

 displayCaptcha: false 

Lo siguiente fue codificar todo lo anterior en PHP, pero el sitio parecía tan extraño que muchos de los bashs fallaron. Así que finalmente me di cuenta de que tenemos que acercarnos un poco más al inicio de sesión del navegador y también sentí que se necesitan retrasos entre las llamadas.

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

Después de ejecutar el código funciona pocas veces y pocas veces no lo hace. Mis observaciones

  • Sólo se permite un inicio de sesión a la vez. Así que no estoy seguro si otros estaban usando el inicio de sesión cuando estaba probando
  • Sin demoras fallaría la mayor parte del tiempo.
  • No hay ninguna razón obvia cuando falla el inicio de sesión excepto que el sitio hace algo en el lado del servidor para bloquear la solicitud

acceso exitoso

El curl.php reutilizable que creé y usé para los métodos de encadenamiento está abajo.

 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('')->asXML(); } function SSLVerifyPeer($verify=false) { curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, $verify); return $this; } } ?> 

El sitio hace una redirección, por lo que necesita agregar

 CURLOPT_FOLLOWLOCATION => 1 

a su matriz de opciones. En caso de duda con cURL, intente

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

dando:

 { "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 } 

Como puede ver, obtuvo un estado de redirección 302 , pero una cuenta de redirect_count fue 0 . Después de agregar la opción, me sale:

 { "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 codifica los parámetros de solicitud y sigue las redirecciones

  $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" ) , ) ); 

@yvesleborg y @ tarun-lalwani dieron las pistas correctas. Necesitas cuidar las cookies y las redirecciones. Pero sin embargo no me funcionó siempre. Supongo que el operador del sitio requiere un tiempo de espera entre las dos solicitudes.

Reescribí un poco su código para jugar con él. 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 = '/\ '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); } 

El script emite dos peticiones al sitio web. La salida de la primera se utiliza para leer el accessCode y para almacenar la cookie de sesión. Luego, después de un pequeño descanso, el segundo se emite utilizando el código de acceso y la información de la sesión junto con las credenciales de inicio de sesión.

Lo probé con PHP5.6 desde un terminal ( php -f mycurl.php ). El script depura toda la información necesaria, genera un comando curl que puede usar en un terminal y registra la información de HTML y cookies en algunos archivos en la misma carpeta como el script.

Ejecutar el script con demasiada frecuencia no funciona. El inicio de sesión no funcionará. Así que tómate tu tiempo y espera unos minutos entre tus bashs. O cambia tu IP;)

Espero eso ayude.

Replicación del problema

Hice lo mismo en Postman como lo hiciste en tu captura de pantalla, pero no pude iniciar sesión:

introduzca la descripción de la imagen aquí

La única diferencia que puedo ver es que su solicitud tenía cookies, lo cual sospecho que es la razón por la que pudo iniciar sesión sin todos los demás campos de entrada. Y parece que hay bastantes campos de entrada:

introduzca la descripción de la imagen aquí

Usando cartero

Por lo tanto, utilicé la intercepción de cartero para capturar todos los campos utilizados durante el inicio de sesión, incluido el código de acceso y captcha, y pude iniciar sesión:

introduzca la descripción de la imagen aquí

Actualización 1

Descubrí que una vez que haya resuelto un captcha para iniciar sesión, una vez que haya finalizado la sesión, podrá iniciar sesión nuevamente sin displayCaptcha y userEnteredCaptcha en sus datos de formulario, siempre que use la misma cookie que usó para iniciar sesión correctamente Solo necesita obtener un accessCode de accessCode válido de la página de inicio de sesión.

Lo más simple que puede hacer, ya que ya lo tiene funcionando en POSTMAN, es representar el código PHP en POSTMAN. Aquí está el enlace a punto de obtener el código PHP de POSTMAN. Luego puedes comparar el ejemplo de POSTMAN con tu código.

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

Lo que se me aparece de inmediato es este ‘hGJfsdnk`1t’. La cita hacia atrás puede ser un carácter de escape ‘`’. Esto podría muy bien ser un error en el que el manejo de errores se redirige a la página de inicio de sesión. POSTMAN probablemente tiene algo integrado para representar el carácter de escape a ‘hGJfsdnk% 601t’. Por lo tanto, esto funciona en POSTMAN, pero no en su código.

Aquí está el estado de esta solicitud:

 { "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 } 

Aquí se muestra el inicio de sesión exitoso.

it doesnt work either in PHP/Python es decir (como ya lo han señalado otros) porque estaba usando la sesión de cookies existente en su navegador, que ya había resuelto el captcha. borre las cookies de su navegador, obtenga una nueva sesión de cookies, y NO RESOLVER EL CAPTCHA, y Postman tampoco podrá iniciar sesión. Any idea what is missing ? varias cosas, entre ellas, varios parámetros de inicio de sesión posteriores ( browserFlag , loginType , __checkbox_dscBasedLoginFlag , y muchos más), también su bucle de encoding aquí tiene un error $str = $str . "$key=$value" . "&"; $str = $str . "$key=$value" . "&"; , prácticamente solo funciona siempre que las claves y los valores solo contengan caracteres [a-zA-Z0-9], y como su usuario Namedenc contiene un carácter de acento grave, su ciclo de encoding es insuficiente. un bucle fijo sería

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

, pero esta es exactamente la razón por la que tenemos la función http_build_query, todo el bucle y el siguiente ajuste se pueden reemplazar con esta única línea:

 $str=http_build_query($params); 

Además, parece que está intentando iniciar sesión sin una sesión de cookies preexistente, eso no va a funcionar. cuando realiza una solicitud GET a la página de inicio de sesión, obtiene una cookie y un captcha único, la respuesta de captcha está vinculada a su sesión de cookies, y debe resolverse antes de intentar iniciar sesión, tampoco proporciona ningún código para tratar El captcha. también, cuando se analiza el elemento de entrada “userName”, se usará de manera predeterminada en “Ingresar nombre de usuario”, que se emite con javascript y se reemplaza con userNamedenc, debe replicar esto en PHP, además, tendrá un elemento de entrada llamado “dscBasedLoginFlag”, que se elimina con javascript, también debe hacer esta parte en php, también tiene un elemento de entrada llamado “Cert”, que tiene un valor predeterminado, pero este valor se borra con javascript, haga lo mismo en php y un elemento de entrada llamado “newUserRegistration”, que se elimina con javascript, haga eso,

esto es lo que debe hacer: realizar una solicitud GET a la página de inicio de sesión, guardar la sesión de cookies y asegurarse de proporcionarla para todas las demás solicitudes, y analizar todos los elementos del formulario de inicio de sesión y agregarlos a su solicitud de inicio de sesión (pero tenga cuidado, hay 2x entradas de formulario, 1 pertenece a la barra de búsqueda, solo analiza a los hijos del formulario de inicio de sesión, no mezcle el 2 ), y recuerde borrar / eliminar las tags de entrada especiales para emular el javascript, como se describe anteriormente, luego realice una solicitud GET a la url captcha, asegúrese de proporcionar la cookie de sesión, resuelva el captcha, luego realice la solicitud final de inicio de sesión, con la respuesta captcha, y userNamedenc y passwordenc y todos los demás elementos analizados en la página de inicio de sesión … . eso debería funcionar. Ahora, resolviendo el captcha programáticamente, el captha no parece demasiado difícil, ya que el craqueo puede ser automatizado, pero hasta que alguien lo haga, puedes usar Deathbycaptcha para que lo haga por ti, pero ten en cuenta que no es un servicio gratuito. .

Aquí hay una implementación de ejemplo completamente probada y funcional, que utiliza mi biblioteca hhb_curl (de https://github.com/divinity76/hhb_.inc.php/blob/master/hhb_.inc.php ), y el api de Deathbycaptcha:

 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 (presumbly 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; } 

Ejemplo de uso: en la terminal, escriba php foo.php | tee test.html php foo.php | tee test.html , después de unos segundos dirá algo como:

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

luego mire el captcha en /home/captcha.png, resuélvalo y escriba en otra terminal: echo ANSWER>/home/captcha.txt , ahora el script iniciará sesión y volcará el html registrado en test.html, que puede abrir en su navegador, para confirmar que realmente inició sesión, captura de pantalla cuando lo ejecuto: https://image.prntscr.com/image/_AsB_0J6TLOFSZuvQdjyNg.png

also note that i made 2 captcha solver functions, 1 use the deathbycaptcha api, and wont work until you provide a valid and credited deathbycaptcha account on line 5 and 6, which is not free, the other 1, solve_captcha2, asks you to solve the captcha yourself, and tells you where the captcha image is saved (so you can go have a look at it), and what command line argument to write, to provide it with the answer. just replace solve_captcha with solve_captcha2 on line 28, to solve it manually, and vise-versa. the script is fully tested with solve_captcha2, but the deathbycaptcha solver is untested, as my deathbycatpcha account is empty (if you would like to make a donation so i can actually test it, send 7 dollars to paypal account divinity76@gmail.com with a link to this thread, and i will buy the cheapest deathbycaptcha credit pack and actually test it)

  • disclaimer: i am not associated with deathbycaptcha in any way (except that i was a customer of theirs a couple of years back), and this post was not sponsored.