J'essaie de me connecter au portail MCA (POST URL: http://www.mca.gov.in/mcafoportal/loginValidateUser.do )
J'ai essayé de me connecter avec l'application POSTMAN sur Google Chrome, ce qui fonctionne bien. Cependant, cela ne fonctionne pas non plus en PHP/Python. Je ne parviens pas à me connecter via PHP/Python
Voici le PHP Code:
$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;
}
Une idée de ce qui manque?
C'est honnêtement l'un des sites étranges que j'ai vus depuis longtemps. La première chose à faire était de savoir comment cela fonctionne. J'ai donc décidé d'utiliser Chrome et de voir ce qui se passe lorsque nous nous connectons avec de mauvaises données.
Observations:
userNamedenc
et respectively
L’approche pour résoudre le problème consistait donc à suivre les étapes ci-dessous.
login.do
loginValidateUser.do
Le formulaire envoie ci-dessous des paramètres
Maintenant, une partie intéressante de la même chose est ci-dessous les données de poste
displayCaptcha:true
userEnteredCaptcha:strrty
Si nous substituons la valeur displayCaptcha
à false, captcha n’est plus nécessaire. Donc, un contournement merveilleux
displayCaptcha: false
Suivant consistait à coder tout ce qui précède en PHP, mais le site semblait si étrange qu'un grand nombre de tentatives ont échoué. Alors, finalement, j'ai réalisé que nous devions nous rapprocher un peu de la connexion du navigateur et que je sentais également qu'il fallait un délai entre les appels.
<?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";
}
Après avoir exécuté le code, cela fonctionne plusieurs fois et peu de fois. Mes observations
Le curl.php
réutilisable que j'ai créé et utilisé pour les méthodes de chaînage est ci-dessous
<?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;
}
}
?>
Le site fait une redirection, vous devez donc ajouter
CURLOPT_FOLLOWLOCATION => 1
à votre tableau d'options. En cas de doute avec cURL, essayez
$status = curl_getinfo($curl);
echo json_encode($status, JSON_PRETTY_PRINT);
donnant :
{
"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
}
Comme vous pouvez le constater, vous avez un statut de redirection 302
, mais un redirect_count
était 0
. Après avoir ajouté l'option, je reçois:
{
"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
}
EDITurl encode les paramètres de la requête et suit les redirections
$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 et @ tarun-lalwani ont donné les bonnes indications. Vous devez vous occuper des cookies et des redirections. Mais néanmoins cela ne fonctionnait pas toujours pour moi. Je suppose que l'exploitant du site a besoin d'un délai d'attente entre les deux demandes.
J'ai réécrit un peu votre code pour jouer avec. 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);
}
Le script envoie deux demandes au site Web. La sortie du premier permet de lire la variable accessCode
et de stocker le cookie de session. Ensuite, après une petite pause, la seconde est émise en utilisant le code d’accès et les informations de session, ainsi que les informations de connexion.
Je l'ai testé avec PHP5.6 à partir d'un terminal (php -f mycurl.php
). Le script débogue toutes les informations nécessaires, génère une commande curl que vous pouvez utiliser dans un terminal et enregistre les informations HTML et les cookies dans certains fichiers du même dossier que le script.
Exécuter le script trop souvent ne fonctionne pas. La connexion ne fonctionnera pas. Alors, prenez votre temps et attendez quelques minutes entre vos essais. Ou changez votre adresse IP;)
J'espère que ça aide.
La chose la plus simple que vous puissiez faire, puisque vous l'avez déjà utilisé dans POSTMAN, consiste à restituer le code PHP dans POSTMAN. Ici est un lien sur le point d'obtenir le code PHP de POSTMAN. Ensuite, vous pouvez comparer l'exemple POSTMAN à votre code.
<?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;
}
Ce qui me saute aux yeux, c’est ce 'hGJfsdnk`1t'. La citation en arrière peut être un caractère d'échappement '' '. Cela pourrait très bien générer une erreur dans laquelle la gestion des erreurs redirige la page de connexion. POSTMAN a probablement quelque chose d'intégré pour rendre le caractère d'échappement en 'hGJfsdnk% 601t'. Ainsi, cela fonctionne dans POSTMAN, mais pas dans votre code.
Voici le statut de cette demande:
{
"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
}
Voici montre la connexion réussie.
Réplication du problème
J'ai fait la même chose dans Postman que vous avez fait votre capture d'écran mais je n'ai pas pu me connecter:
La seule différence que je peux voir est que votre demande comportait des cookies, ce qui, je suppose, est la raison pour laquelle vous avez pu vous connecter sans tous les autres champs de saisie. Et il semble y avoir beaucoup de champs de saisie:
Using Postman
Donc, j'ai utilisé postman intercept pour capturer tous les champs utilisés lors d'une connexion, y compris le captcha et le code d'accès, et j'ai pu me connecter:
_ {Mise à jour 1} _
J'ai découvert qu'une fois le captcha résolu, vous pouvez vous reconnecter sans displayCaptcha
et userEnteredCaptcha
dans vos données de formulaire, fourni que vous utilisiez le même cookie celui que vous avez utilisé pour vous connecter avec succès. Vous devez simplement obtenir une accessCode
valide à partir de la page de connexion.
it doesnt work either in PHP/Python
c'est (comme d'autres l'ont déjà souligné) parce que vous utilisiez la session de cookie existante de votre navigateur, qui avait déjà résolu le captcha. effacez les cookies de votre navigateur, obtenez une nouvelle session de cookie et NE RÉSOLVEZ PAS LE CAPTCHA, et Postman ne pourra pas non plus se connecter. Any idea what is missing ?
plusieurs choses, parmi elles, plusieurs paramètres postérieurs à la connexion (browserFlag
, loginType
, __checkbox_dscBasedLoginFlag
, et bien d’autres), et votre boucle d’encodage ici est boguée $str = $str . "$key=$value" . "&";
, ne fonctionne que tant que les clés et les valeurs ne contiennent que des caractères [a-zA-Z0-9], et que votre userNamedenc contient un caractère accent Grave, votre boucle de codage est insuffisante. une boucle fixe serait
foreach($params as $key=>$value){
$str = $str . urlencode($key)."=".urlencode($value) . "&";
}
$str=substr($str,0,-1);
, mais C’est précisément pourquoi nous avons la fonction http_build_query, cette boucle entière et le découpage suivant peuvent être remplacés par cette seule ligne:
$str=http_build_query($params);
semble également que vous essayez de vous connecter sans session de cookie préexistante, , cela ne fonctionnera pas. Lorsque vous envoyez une requête GET à la page de connexion, vous obtenez un cookie et un captcha unique, La réponse captcha est liée à votre session de cookie et doit être résolue avant toute tentative de connexion, vous ne fournissez pas non plus de code pour traiter le captcha. de plus, lors de l'analyse de l'élément d'entrée "userName", il utilisera par défaut "Enter Username", qui est lié à javascript et remplacé par userNamedenc. Vous devez le répliquer en PHP, . Un élément d'entrée sera également présent. nommé "dscBasedLoginFlag", qui est supprimé avec javascript, vous devez également faire cette partie en php, également il a un élément d'entrée nommé "Cert", qui a une valeur par défaut, mais cette valeur est effacée avec javascript, faites la même chose en php, et un élément d'entrée nommé "newUserRegistration", qui est supprimé avec javascript, faites-le,
voici ce que vous devez faire: envoyez une demande GET à la page de connexion, enregistrez la session de cookie et assurez-vous de la fournir pour toutes les demandes ultérieures, puis analysez tous les éléments du formulaire de connexion et ajoutez-les à votre demande de connexion (mais faites attention, il y a 2x entrées de formulaire, 1 appartient à la barre de recherche, n'analysez que les enfants du formulaire de connexion, ne mélangez pas les 2 ), et n'oubliez pas d'effacer/supprimer les balises d'entrée spéciales pour émuler le javascript , comme décrit ci-dessus, puis envoyez une demande GET à l'URL captcha, assurez-vous de fournir le cookie de session, résolvez le captcha, puis faites la demande de connexion finale, avec la réponse captcha, et userNamedenc et passwordenc ainsi que tous les autres éléments analysés à partir de la page de connexion ... cela devrait fonctionner. maintenant, résoudre le captcha par programmation, le captha n'a pas l'air trop dur, le craquage peut probablement être automatisé, mais jusqu'à ce que quelqu'un le fasse, vous pouvez utiliser Deathbycaptcha pour le faire à votre place, Notez cependant que ce n'est pas un service gratuit.
voici un exemple d'implémentation de travail entièrement testé et utilisant ma bibliothèque hhb_curl (à partir de https://github.com/divinity76/hhb_.inc.php/blob/master/hhb_.inc.php ), et l'App Deathbycaptcha :
<?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;
}
exemple d'utilisation: dans le terminal, écrivez php foo.php | tee test.html
, après quelques secondes, il affichera quelque chose comme:
the captcha is saved in /home/captcha.png
waiting for you to solve it by doing: echo ANSWER>/home/captcha.txt
ensuite, regardez le captcha dans /home/captcha.png, résolvez-le et écrivez dans un autre terminal: echo ANSWER>/home/captcha.txt
, le script va maintenant se connecter et vider le code html connecté dans test.html, que vous pouvez ouvrir dans votre navigateur, pour confirmer qu'il est réellement connecté, capture d'écran lorsque je l'exécute: https://image.prntscr.com/image/_AsB_0J6TLOFSZuvQdjyNg.png
notez également que j’ai créé 2 fonctions de résolution du captcha, 1 utilisation de l’API deathbycaptcha, et ne fonctionnera pas tant que vous ne fournissez pas un compte deathbycaptcha valide et crédité sur les lignes 5 et 6, ce qui n’est pas gratuit. captcha vous-même et vous indique où l'image captcha est enregistrée (pour que vous puissiez la consulter) et quel argument de ligne de commande écrire pour lui fournir la réponse. remplacez simplement solve_captcha
par solve_captcha2
à la ligne 28, pour le résoudre manuellement et inversement. le script est entièrement testé avec resol_captcha2, mais le solveur deathbycaptcha n’a pas été testé car mon compte deathbycatpcha est vide (si vous souhaitez faire un don afin que je puisse le tester, envoyez 7 dollars au compte Paypal [email protected] avec un lien vers ce fil, et je vais acheter le pack de crédit de deathbycaptcha le moins cher et le tester)