Я не могу войти на сайт через curl - PullRequest
1 голос
/ 14 марта 2020

Я не могу понять, что я делаю неправильно. Есть сервисный сайт: https://demo.moneta.ru/login.htm. Обычная форма с токеном. Стучу по странице, сохраняю куки, беру токен из формы. Следующий запрос я отправляю на адрес из данных формы. С печеньем и токеном. Я получаю фига. 401.

Я все проверил, отправляю одинаковые данные, одинаковые заголовки. Скажите, что мне не хватает?

$receipt = new Receipt;

$receipt->get_scrf();
echo $receipt->get_auth();

Class Receipt {
    private $scrf;

    private $login_page_url = 'https://demo.moneta.ru/login.htm';
    private $login_action_url = 'https://demo.moneta.ru/login';

    private $login = 'LOGIN';
    private $password = "PASSWORD";

    public function get_auth(){
    $headers = [
        'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
        'Accept-Encoding: gzip, deflate, br',
        'Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7',
        'Cache-Control: max-age=0',
        'Origin: https://demo.moneta.ru',
        'Referer: https://demo.moneta.ru/login.htm',
        'Sec-Fetch-Dest: document',
        'Sec-Fetch-Mode: navigate',
        'Sec-Fetch-Site: same-origin',
        'Sec-Fetch-User: ?1',
        'Upgrade-Insecure-Requests: 1',
        'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36',
        'Content-Type: application/x-www-form-urlencoded',
        'Connection: keep-alive'
    ];

        $post = [
            'state' => $this->scrf,
            'target' => 'desktop',
            'login' => $this->login,
            'password' => $this->password
        ];

        return $this->get_page($this->login_action_url, $post, $headers);
    }

    public function get_scrf(){
        $page_html = $this->get_page($this->login_page_url);

        preg_match('/\<input\ type\=\"hidden\"\ name\=\"state\"\ value\=\"([0-9a-z\-]+)\"\>/', $page_html, $matches, PREG_OFFSET_CAPTURE);

        if(isset($matches[1][0])){
            $this->scrf = $matches[1][0];
            return $matches[1][0];
        }
        return null;
    }

    private function get_page($url, $post=null, $headers=null){
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url );
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__).'/cookie.txt');
        curl_setopt($ch, CURLOPT_COOKIEFILE,  dirname(__FILE__).'/cookie.txt');
        curl_setopt($ch, CURLOPT_POST, $post!==null );

        if($headers){
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }

        if($post){
            curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
        }
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }
}

Запрос из браузера

1 Ответ

1 голос
/ 17 марта 2020

У вас есть

curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

, где $post - ассоциативный массив.

Из документации

Если value является массивом, заголовок Content-Type будет установлен в multipart / form-data .

Это не поведение формы и конфликтует с заголовком Content-Type, который вы явно задали:

'Content-Type: application/x-www-form-urlencoded'

Попробуйте передать данные POST в curl_setopt($ch, CURLOPT_POSTFIELDS, ... как строка в кодировке URL;

вам просто нужно http_build_query()

curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query( $post ) );
...