Продолжая цикл статей посвященный парсерам и всем, что с ними связано. В этой статье расскажу про то, как легко можно авторизоваться на любом сайте при помощи библиотеку cUrl php. Для примера я взял один Украинский портал, к которому я собственно и буду подбирать ключики. Для работы нам также понадобится библиотека simple_html_dom
Авторизацию будем проходить на сайте http://tender.me.gov.ua , не буду создавать лишних ссылок, чтобы не накрыть нашу лавочку.
Для начала зарегистрируйтесь на сайте, чтобы иметь тестовые логин-пароль для входа на сайт.
На сайте мы видим ничем не примечательную форму авторизации.
"Внутренности" у нее тоже ничем не примечательны
<form id="login" name="login" method="post" action="/EDZFrontOffice/menu/uk/;jsessionid=c4651e96f5c2b9afb08776cbd1a5" enctype="application/x-www-form-urlencoded"> <input type="hidden" name="login" value="login" /> <input id="login:login" type="text" name="login:login" class="login" maxlength="80" /> <input id="login:password" type="password" name="login:password" value="" maxlength="80" class="login" /> <input type="image" src="images/t_login_button.png;jsessionid=c4651e96f5c2b9afb08776cbd1a5" name="login:j_id_id254" alt="Вхід" /> <input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="j_id1:j_id2" autocomplete="off" /> </form>
Итак смотрим, что форма авторизации отправляет при аутентификации. Для этого возпользуемся Google Chrome, открываем в нем сайт, затем Инструменты->Инструменты разработчика. Далее переходим на вкладку Network. Для браузера Opera Меню->Страница->Средства Разработки->Open Opera DragOnFly и вкладка Сеть. Хоть я и фанат Оперы, но на мой взгляд продукт от компании Google немного удобнее. Я конечно не про браузер =)
Теперь авторизуемся на сайте, смотрим, что посылает форма при сабмите.
Видим, что форма посылает следующие параметры
login:login login:login:{loginmail} login:password:{password} login:j_id_id254.x:8 login:j_id_id254.y:7 javax.faces.ViewState:j_id1:j_id2
Попробуем решить задачу в лоб и отправить эти данные простым массивом. Сразу учтем, что данные отправляются на защищенный ssl url, по протоколу https. Это следует учитывать при отправке данных в cUrl. Рассказывать, как работает SSL в рамках данной статьи я не стану, скажу лишь, что сертификаты, которыми обмениваются две стороны, сами по себе ничего не говорят о его обладателе. Они нужны лишь для того, чтобы передать открытый ключ, обеих сторон и служат для шифрования канала связи. Т.е. мы можем проверять наличие ssl, и подключать сертификат в cUrl, но это будет служить пользу только нам, сервер не может узнать пользуемся ли мы сертификатом, или используем незащищенный канал связи.
//О том, что мы авторизовались будем судить по наличию формы logout function isAuth( $data ){ return preg_match('#<form[^>]+id="logout"#Usi',$data); } $ch = curl_init(); $url = 'https://tender.me.gov.ua/EDZFrontOffice/menu/uk/'; 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);// таймаут4 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);// просто отключаем проверку сертификата curl_setopt($ch, CURLOPT_POST, 1); // использовать данные в post curl_setopt($ch, CURLOPT_POSTFIELDS, array( 'login'=>'login', 'login:login'=>'mylogin@sitename.ru', 'login:password'=>'password', 'login:j_id_id254.x'=>8, 'login:j_id_id254.y'=>7, 'javax.faces.ViewState'=>'j_id1:j_id2', )); echo isAuth($data = curl_exec($ch))?'Success':'Failed'; curl_close($ch);
Запускаем и видим, что ничего не получилось. Сайт просто так не сдался. Мы не учли одну вещь, данные об авторизации должны быть сохранены в cookie. Для этого добавим две строчки в код, к примеру после curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
... 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'); ...
И снова мимо. Обратим внимание, что форма помимо стандартных логина-пароля, отправляет еще 3 динамических поля. Данные в них все время разные и генерируются при обновлении страницы. Значит, нужно загрузить страницу, скопировать эти данные и проходить аутентификацию уже с ними. Для этого немного "облагородим" код, заключив запрос данных с сервера cUrl'ом в отдельную функцию. Все отличие get запроса от post, заключается в том, что при пост запросе отправляются данные CURLOPT_POSTFIELDS
function request($url,$post = 0){ $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);// таймаут4 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!==0 ); // использовать данные в post if($post) curl_setopt($ch, CURLOPT_POSTFIELDS, $post); $data = curl_exec($ch); curl_close($ch); return $data; }
Попытаемся выдернуть значения переменных полей
$data = request('https://tender.me.gov.ua/EDZFrontOffice/'); include 'simple_html_dom.php'; $data = str_get_html($data); $auth = array( 'login'=>'login', 'login:login'=>'***************', 'login:password'=>'************l', 'login:j_id_id254.x'=>$data->find('input[name="login:j_id_id254.x"]',0)->value, 'login:j_id_id254.y'=>$data->find('input[name="login:j_id_id254.y"]',0)->value, 'javax.faces.ViewState'=>$data->find('input[name="javax.faces.ViewState"]',0)->value, ); $data->clear(); unset($data); print_r($auth);
Оказывается, что поле login:j_id_id254.x и поле login:j_id_id254.y создаются и заполняются js скриптом. Попробуем оставить их как были
$url = 'https://tender.me.gov.ua/EDZFrontOffice/menu/uk/'; $data = request('https://tender.me.gov.ua/EDZFrontOffice/'); include 'simple_html_dom.php'; $data = str_get_html($data); $auth = array( 'login'=>'login', 'login:login'=>'site@sitename.ru', 'login:password'=>'password', 'login:j_id_id254.x'=>10, 'login:j_id_id254.y'=>11, 'javax.faces.ViewState'=>$data->find('input[name="javax.faces.ViewState"]',0)->value, ); $data->clear(); unset($data); echo isAuth(request($url,$auth))?'Success':'Failed';;
Вот и все, сайт побежден. Далее работаем с ним, как с обычным сайтом. Данные о том, что Ваш скрипт никто иной, как авторизованный пользователь бережно хранятся в cookie.
Скрипт работает, но в более сложных случаях, приходиться эмулировать выполнение js скриптов, либо просто выяснять механизм их работы, чтобы заполнить те самые динамически заполняемые поля. К сожалению, этому не научишь, все зависит от конкретной задачи и изобретательности программиста. За примерами далеко ходить не надо, попробуйте для интереса создать скрипт, который бы отправлял автоматически, комментарии на xdan.ru. Желаю удачи =)
Комментарии
Как мне выяснить, что именно недает авторизации случится?
Допустим, если там есть js - key, как его вычислить? Что значит "посмотреть в инспекторе распакованный js" и как я отличу нужный мне js?)
#]+id="logout"#Usi
В результате если в строке $data есть форма с id="logout" то preg_match вернет true, значит на странице есть форма с выходом. На вашем сайте все может быть гораздо иначе, но принцип тот же - ищем на странице то, что на ней нет до авторизации
т.е. если взять логин/пасс из кода и зайти под браузером, вбить поиск по артикулу, мало того что результаты будут отличаться так еще и вываливается сообщение о необходимости регистрации для получения актуальных данных.
Голову ломаю 2й день =/
{
return preg_match('#]+id="Authorization"#Usi',$data);
}
$ch = curl_init();
$url = 'http://www.autodoc.ru/';
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);// таймаут4
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)');
curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__).'/cookie.txt'); // сохранять куки в файл
curl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__).'/cookie.txt');
curl_setopt($ch, CURLOPT_POST, 1); // использовать данные в post
curl_setopt($ch, CURLOPT_POSTFIELDS, array(
'returnUrl'=>'/',
'UserName'=>'MANGO-1344',
'RememberMe'=>'true',
'RememberMe'=>'false',
'Password'=>'QWEASDQWE',
));
isAuth($data = curl_exec($ch))?($Success=1):($Success=0);
if ($Success == 1)
{
curl_setopt($ch, CURLOPT_URL, 'http://www.autodoc.ru/Web/price/art/95659676?analog=on&access=2');
curl_setopt($ch, CURLOPT_HEADER, 0); // пустые заголовки
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // возвратить то что вернул сервер
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // следовать за редиректами
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);// таймаут4
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)');
curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__).'/cookie.txt'); // сохранять куки в файл
curl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__).'/cookie.txt');
$out = curl_exec($ch);
echo $out;
}
curl_close($ch);
Но однако у меня не получается пройти авторизацию mail.arenda-gold.ru
Делал вроде всё по статье, но не выходит, поможет кто?
И заодно на сайте Сландо не понятно каким образом происходит авторизация.
Если не затруднит вас, подскажите как разобраться с этим?
у меня после авторизации нету формы, таблицами все выстроено, как правильно написать, что бы судить по наличию этого кода на странице, что авторизация успешна
так будет правильно?
Делаю по вашему образцу авторизацию на др. сайте, только одно поле меняется с name="rnd", его значение вытаскиваю при помощи регулярки.. вроде все правильно, а авторизоваться не получается.. не подскажите, что не так?
Вот код:
$url4 = 'http://www.palaris-nn.ru/shop/1559331/edit';
$ch = curl_init();
@curl_setopt($ch, CURLOPT_URL, $url4);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT, 3);
$resultnew = curl_exec($ch);
preg_match_all("/name=\"rnd\" value=\"(.*)\"/isU", $resultnew, $masnew);
$perem_rnd = $masnew[1][0];
$data = array ('user' => '***', 'password' => '***', 'rem' => '1', 'a' => '2', 'ajax' => '1', 'rnd' => $perem_rnd, '_tp_' => 'xml');
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt ($ch, CURLOPT_COOKIEFILE, '/var/www/u38746/data/www/new.palaris-nn.ru/massur lphp/cooki.txt'); // Сюда будем записывать cookies, файл в той же папке, что и сам скрипт
curl_setopt ($ch, CURLOPT_COOKIEJAR, '/var/www/u38746/data/www/new.palaris-nn.ru/massur lphp/cooki.txt');
$html = curl_exec($ch);
echo $html;
curl_close($ch);
Встал в ступор просто.
Спасибо!
с возможностью подключения прокси с логином и паролем)
Алгоритм простой:
указываю в переменной, логин/номер телефона и пароль,
далее прокси через который соединяемся,
скрипт входит в аккаунт и считываем статус аккаунта "стандартный, упрощенный".