Авторизация в Яндексе – php, curl и cookies

Опубликовано 3 мая, 2009 в PHP

В прошлом посте мы делали POST запросы, а сегодня мы будем авторизироваться в Яндексе. Помимо отправки POST формы с логином и паролем, нам необходимо будет также авторизироваться, тоесть сохранить нужные куки и отдавать их в последующих запросах.

Поставим себе следующую задачу – получать содержимое панели вебмастера с помощью PHP.

Все знают, как при помощи PHP получить содержание той или иной страницы. Но в нашей задаче есть одна загвоздка – чтобы получить страницу с сайтами определенного аккаунта, нам нужно войти под этим аккаунтом. Для этого необходимо отправить POST форму отсюда. Внимательно изучаем все поля этой формы, нам необходимо отправить Яндексу все эти поля. В ответ Яндекс даст нам куку, которую мы должны сохранить и отдавать обратно Яндексу при каждом следующем посещении страницы с инфой, доступной только авторизированным пользователям.

Вот, собственно, функция авторизации:

<?php
$url = "http://passport.yandex.ru/passport?mode=auth"; //УРЛ, куда отправлять данные

/*
Переменные, которые мы будет отправлять Яндексу в виде POST запроса:
*/
$login = 'test'; //Логин
$passwd = 'test'; //Пароль
$user_cookie_file = $_SERVER['DOCUMENT_ROOT'].'/cookies.txt'; //Полный путь до файла, где будем хранить куки
$idkey = '3121235564020nVDfxvth2'; //Хрен знает что
$retpath = 'http://webmaster.yandex.ru/'; //Откуда мы пришли на страницу авторизации
$timestamp = ''; //Хрен знает что
$twoweeks = 'yes'; //Две недели какие-то
$In = 'Войти'; //Кнопка входа

/*
Функция:
*/
function auth($url) {
	global $user_cookie_file, $idkey, $retpath, $timestamp, $login, $passwd, $twoweeks, $In; // Получаем все POST данные
/*
Небольшая прелюдия с инифиализацией cURL и прочей шулухой
*/
	$ch = curl_init($url);
	curl_setopt($ch, CURLOPT_URL,$url);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
	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_COOKIEFILE, $user_cookie_file); //Куки раз
	curl_setopt($ch, CURLOPT_COOKIEJAR,  $user_cookie_file); //Куки два

	curl_setopt($ch, CURLOPT_POST,1); //Будем отправлять POST запрос

/*
Формируем и отправляем тот самый POST запрос.
Как видите, это простая строка, мало чем отличающаяся от GET.
*/
	curl_setopt($ch, CURLOPT_POSTFIELDS,"idkey=$idkey&retpath=$retpath&timestamp=$timestamp&login=$login&passwd=$passwd&twoweeks=$twoweeks&In=$In");
	$html = curl_exec($ch);
	curl_close($ch);
	return $html; //Возвращаем ответ Яндекса
}

auth($url); // Авторизируемся.
?>

С авторизацией все понятно – отправили логин, пароль и прочую информацию, сохранили отданные Яндексом куки. Теперь нам необходима функция, которая будет отдавать сохраненные куки Яндексу и получать ответ, тоесть ходить по защищенным страницам как добропорядочный живой юзер с настоящего добропорядочного браузера.

Вот эта функция:

<?php
function browser($url) {
	$user_cookie_file = $_SERVER['DOCUMENT_ROOT'].'/cookies.txt'; //Получаем сохраненный после авторизации файл с куками.
	$ch = curl_init($url);
	curl_setopt($ch, CURLOPT_URL,$url);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
	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_COOKIEFILE, $user_cookie_file); //Подставляем куки раз
	curl_setopt($ch, CURLOPT_COOKIEJAR,  $user_cookie_file); //Подставляем куки два
	$html = curl_exec($ch);
	curl_close($ch);
	return $html; //Возвращаем ответ
}
echo browser('http://webmaster.yandex.ru/'); //Безпрепятственно выводим заветную инфу
?>

Надо также сказать, что авторизироваться достаточно один раз, а потом в течение 2х недель просто юзать функцию browser();

Думаю, вы понимаете, что описанным способом можно авторизироваться не только на Яндексе, а вообще где угодно.

Удачи.





Комментарии «Авторизация в Яндексе – php, curl и cookies»:
Комментариев: 30. Обязательно оставьте свой!
lis 05.05.2009 в 8:27

Что-то у меня совсем не получилось авторизоваться :( . Делал все в точности как в статье (логин с паролем ставил свои) а в ответ от функции browser – тишина. Если в ней еще установить параметр

curl_setopt ($ch, CURLOPT_HEADER, true);

то приходит ответ:

HTTP/1.1 302 Moved Temporary
Connection: Keep-Alive
Date: Tue, 05 May 2009 04:34:59 GMT
Location: http://passport.yandex.ru/passport?mode=auth&retpath=http%3A%2F%2Fwebmaster.yandex.ru%2Fwmconsole%2F
Server: BAIDA/1.0.0
Transfer-Encoding: Chunked

Если я правильно понимаю – авторизация в функции auth не проходит (хотя файлик cookies.txt формируется) и в функции browser яндекс опять перенаправляет на страницу авторизации

lis 05.05.2009 в 12:20

Разобрались где был касяк, в

curl_setopt($ch, CURLOPT_POSTFIELDS,»idkey=$idkey&retpath=$retpath&timestamp=$timestamp&login=$login&passwd=$passwd&twoweeks=$twoweeks&In=$In»);

& нужно заменить на &

pistol 05.05.2009 в 12:30

lis, спасибо, исправил.

Косяк редактора вордпресса в том, что со вставленным кодом в теге pre и вообще с html делает что захочет после публикации.

sarqil 11.05.2009 в 19:37

Ух ты ж блин, спасибо! полчаса уже с авторизацией парюсь, потом про гугл вспомнил :)

Enshtein 22.06.2009 в 15:20

Чё-та нихрена это не работает….у меня даже cookies.txt не создаётся….первый раз юзаю curl….
бля помогите разобраться с этой фигнёй….уж очень нада

Enshtein 22.06.2009 в 15:52

вроде разобрался….

Sharkmanru 03.07.2009 в 6:34

Почему-то не работает… хотя подставляю все параметры правильно, странно…

pistol 03.07.2009 в 6:39

Sharkmanru, необходимо дебажить – проверь, что возвращает Яндекс (какие заголовки), создается ли файл куков (права необходимо выставить, если не создается) и т.д. Пока сказать в чем проблема может быть невозможно.

Sharkmanru 03.07.2009 в 6:43

Да я с консоли проверяю, всё верно, это точно…

pistol 03.07.2009 в 6:51

Еще раз проверил, у меня работает, значит, Яндекс не менял ничего в способе и алгоритмах авторизации. Остается только дебажить, каждую переменную и каждое действие. Проблема должна лежать где-то на поверхности :)

insane 03.08.2009 в 11:48

скрипт не заходит, я его запускаю и никакого ответа нет, в чем дело может быть? куки не пишет вообще захожу пустая страница, с шела тоже!

pistol 03.08.2009 в 13:32

insane, дебаж. Если файл куков не создается, возможно, прав нет. Посмотри, что возвращает Яндекс, само по себе auth($url) и не должно ни на что отвечать, замени на echo auth($url). Вывод ошибок включи.

Миллион причин может быть.

pablobablo 07.11.2009 в 22:58

У меня тоже была проблема. Оказалось что лишний амперсанд (&) в строке параметров ставил.

Это:
curl_setopt ( $ср, CURLOPT_POSTFIELDS, ‘name=pablo&pass=1234&’);

Исправил на это:
curl_setopt ( $ср, CURLOPT_POSTFIELDS, ‘name=pablo&pass=1234′);

Надеюсь, что кому-нибудь поможет.
Сам 5 часов потратил на поиск ошибки.

Спасибо можно сказать тут: Z157719302428 :)

Orlenko K.N. 26.11.2009 в 14:25

А для гугля можете пример авторизации привести? А-то сижу вот чайник курла… там параметров километрище.. помогите плиз))

Orlenko K.N. 26.11.2009 в 14:37

Вот, вроде выдернул:

Логин

Пасс

Помогите с составлением, пожалста

pistol 26.11.2009 в 15:41

Orlenko K.N., в гугле все сложнее намного. На каком-то форуме наблюдал, как бились над этим, так и не добились ничерта. На досуге попробую авторизироваться.

Orlenko K.N. 27.11.2009 в 8:07

Пробую вот по приведённому выше примеру сделать, FALSE выдаёт и всё тут
http://www.google.com FALSE /accounts/ TRUE 0 GoogleAccountsLocale_session ru
Вот так вот..

Дмитрий 15.12.2009 в 0:10

Неповерите, но не работает!!!!!
Куки в файл пишет, а на запрос browser(ссылка) в ответ пустая страница приходит, такое ощющение что куки назад не отсылает, а может потому, что Locationв первом скрипте не выполнился….

pistol 15.12.2009 в 8:39

Проверил у себя – работает. Значит – виной всему являются какие-то обстоятельства, нужно дебажить, найти это обстоятельство.

и еще –
echo browser(‘http://webmaster.yandex.ru/wmconsole/’);
сейчас там ничего нет, перенесли на:
echo browser(‘http://webmaster.yandex.ru/’);

Дмитрий 15.12.2009 в 12:46

Забираю свои слова обратно, все работает все ок!!!!
Причина оказалась echo browser(’http://webmaster.yandex.ru/’);
Спасибо АВТОРУ!!!!
Побольше бы таких статей и людей, которые пишут такие статьи в которых Разжовывают как и что работает, все с коментами, все супер!!!
Ещо раз спасибо АВТОРУ, очень помог!!!
Сайт в закладки обезательно…

yAnTar 02.01.2010 в 18:28

Спасибо за статью, как раз искал то что надо, но поправьте в примере http://webmaster.yandex.ru/wmconsole/, а то пришлось комменты все читать, чтобы понять, почему лажа.

S10 28.01.2010 в 20:18

Спасибо. На основе реализовал простенький класс для пхп4 с 2мя функциями(для POST & GET запросов :) ), чтоб постоянно одинаковый код не вбивать и не искать:)

S10 28.01.2010 в 20:32

Кстати, рекомендую также добавить
curl_setopt($connect, CURLOPT_FOLLOWLOCATION, TRUE);

Ибо при логине на таких проектах, как мой мир, идет редирект между 4-5 страничками, и нам желательно их все обойти, а не встревать на 1ой.

Алекс 01.02.2010 в 15:12

На маил ру не получается зайти (ничего др. еще не пробывал.) еще при авторизации ответа никакого не возвращается, уки создаются нормально
вот содержимое куки (ящик скрыл ХХХХХХ)
# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This file was generated by libcurl! Edit at your own risk.

mail.ru FALSE / FALSE 0 PHPSESSID 05121a912d8d09c1fce140885fb7ce34
.mail.ru TRUE / FALSE 1272800713 Mpop 1265024713:06065e606a056b5b190502190f1d00071c06074f6a5d5e465e07030401031e0902011e4e4e4f464746404246145c555e551f4243:XXXXXXXXX@mail.ru:
.mail.ru TRUE / FALSE 1265197511 server 2
mail.ru FALSE / FALSE 0 uid 179799
вчем может быть проблема???

Алекс 01.02.2010 в 15:35

Во, лучше юзайте это, у меня все получилось

$cookie = $_SERVER['DOCUMENT_ROOT'].’/img/cookies.txt’;
$url = "http://g2.botva.mail.ru/login.php";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT, 3);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
curl_setopt($ch, CURLOPT_NOBODY, 0);
curl_setopt($ch, CURLOPT_HEADER, 1);
$result = curl_exec($ch);
curl_close($ch);
$url = "http://g2.botva.mail.ru/login.php";
$post = "login=*****&pass=******";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
curl_setopt($ch, CURLOPT_REFERER, "http://g2.botva.mail.ru/login.php");
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT, 3);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
curl_setopt($ch, CURLOPT_NOBODY, 0);
curl_setopt($ch, CURLOPT_HEADER, 1);
$result = curl_exec($ch);
curl_close($ch);
?>

Acses 15.02.2010 в 16:19

Спасибо, доступно объяснено.
Интересно было бы посмотреть на использование куки с помощью сокетов ;)

Said 05.04.2010 в 15:27

Если вы посниферите что шлет браузер во время авторизации на мыле яндекса, то заметите что post-зпароса там нет!

яша каким-то js скриптом формирует куки, записывает и шлет методом get на какой-то адрес, причем данные не передает в строке запроса. логин, base64 хеша и ещё что-то в куках передается на его сервер.

riyuzakki 21.04.2010 в 17:51

Возникла проблема с переносом скрипта, использующего cURL, на другую машину. Суть: на другой машине передаются не все полученные куки.

Кусок дебаг-лога с первой машины (curl –version
curl 7.20.0 (i686-pc-linux-gnu) libcurl/7.20.0 OpenSSL/0.9.8n zlib/1.2.4
Protocols: dict file ftp ftps http https imap imaps ldap ldaps pop3 pop3s rtsp smtp smtps telnet tftp
Features: Largefile NTLM SSL libz):

< HTTP/1.1 302 Found
< Date: Wed, 21 Apr 2010 13:32:40 GMT
< Server: Microsoft-IIS/6.0
< X-Powered-By: ASP.NET
< X-AspNet-Version: 2.0.50727
< Content-Encoding: gzip
< Location: /Reports/Transit.aspx
* Added cookie B2BUser="" for domain b2b.yyy.ru, path /, expire 1271770360
< Set-Cookie: B2BUser=; expires=Tue, 20-Apr-2010 13:32:40 GMT; path=/
* Added cookie 5AFDF04C-F06D-4049-8371-05121B247D87="CFFE909AC8073DCDC9A38856EBCA720C1C39F7E708E17E36646FDF225EE035250D0D54AAA9B67A08D987C22BC9A2C7B50421E58A4DFF76069E8788DD51399D58E52ADEB0337008A0AD04A9B2D85A221A" for domain b2b.yyy.ru, path /, expire 1271862760
< Set-Cookie: 5AFDF04C-F06D-4049-8371-05121B247D87=CFFE909AC8073DCDC9A38856EBCA720C1C39F7E708E17E36646FDF225EE035250D0D54AAA9B67A08D987C22BC9A2C7B50421E58A4DFF76069E8788DD51399D58E52ADEB0337008A0AD04A9B2D85A221A; expires=Wed, 21-Apr-2010 15:12:40 GMT; path=/; HttpOnly
< Cache-Control: private
< Content-Type: text/html; charset=utf-8
< Content-Length: 4082
<
* Ignoring the response-body
* Connection #0 to host b2b.yyy.ru left intact
* Issue another request to this URL: ‘https://b2b.yyy.ru/Reports/Transit.aspx’
* Violate RFC 2616/10.3.3 and switch from POST to GET
* Re-using existing connection! (#0) with host b2b.yyy.ru
* Connected to b2b.yyy.ru (xxx) port 443 (#0)
> GET /Reports/Transit.aspx HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0)
Host: b2b.yyy.ru
Accept-Encoding: gzip
Referer:
Cookie: 5AFDF04C-F06D-4049-8371-05121B247D87=CFFE909AC8073DCDC9A38856EBCA720C1C39F7E708E17E36646FDF225EE035250D0D54AAA9B67A08D987C22BC9A2C7B50421E58A4DFF76069E8788DD51399D58E52ADEB0337008A0AD04A9B2D85A221A; B2BAccept=21.04.2010 17:32:38; ASP.NET_SessionId=qlcbxrmwoql1r5nfbiyudu55
Accept: image/gif, image/x-bitmap, image/jpeg, image/pjpeg
Connection: Keep-Alive
Content-type: application/x-www-form-urlencoded

Со второй машины (curl –version
curl 7.18.2 (i486-pc-linux-gnu) libcurl/7.18.2 OpenSSL/0.9.8n zlib/1.2.3.3 libidn/1.8 libssh2/0.18
Protocols: tftp ftp telnet dict ldap ldaps http file https ftps scp sftp
Features: GSS-Negotiate IDN IPv6 Largefile NTLM SSL libz):

< HTTP/1.1 302 Found
< Date: Wed, 21 Apr 2010 14:12:08 GMT
< Server: Microsoft-IIS/6.0
< X-Powered-By: ASP.NET
< X-AspNet-Version: 2.0.50727
< Content-Encoding: gzip
< Location: /Reports/Transit.aspx
* Added cookie B2BUser="" for domain b2b.yyy.ru, path /, expire 1271772728
< Set-Cookie: B2BUser=; expires=Tue, 20-Apr-2010 14:12:08 GMT; path=/
* Added cookie 5AFDF04C-F06D-4049-8371-05121B247D87="30FE90A67B8B88104DD13D3A051B9B28B11D9327C00BEBBAB14496056147D8EF39485022165247C52B49B4856958524AADD4385827F6A231C79E2DFCFB792240C96C329584F2A796FB3DBD871AF55C43" for domain b2b.yyy.ru, path /, expire 1271865128
< Set-Cookie: 5AFDF04C-F06D-4049-8371-05121B247D87=30FE90A67B8B88104DD13D3A051B9B28B11D9327C00BEBBAB14496056147D8EF39485022165247C52B49B4856958524AADD4385827F6A231C79E2DFCFB792240C96C329584F2A796FB3DBD871AF55C43; expires=Wed, 21-Apr-2010 15:52:08 GMT; path=/; HttpOnly
< Cache-Control: private
< Content-Type: text/html; charset=utf-8
< Content-Length: 4082
<
* Ignoring the response-body
* Connection #0 to host b2b.yyy.ru left intact
* Issue another request to this URL: ‘https://b2b.yyy.ru/Reports/Transit.aspx’
* Disables POST, goes with GET
* Re-using existing connection! (#0) with host b2b.yyy.ru
* Connected to b2b.yyy.ru (xxx) port 443 (#0)
> GET /Reports/Transit.aspx HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0)
Host: b2b.yyy.ru
Accept-Encoding: gzip
Referer:
Cookie: B2BAccept=21.04.2010 18:12:07; ASP.NET_SessionId=fzkch2bm3c1noyinxdx4pnzr
Accept: image/gif, image/x-bitmap, image/jpeg, image/pjpeg
Connection: Keep-Alive
Content-type: application/x-www-form-urlencoded

На второй машине кука принимается, сохраняется в файл, но отправляется не вся. Очевидно, что есть различия в версиях курла, но может есть некая опция? Не хотельсь бы ковыряться в зависимостях дебиана…


Куку сохраняет, но авторизация не срабатывает. И есть мнение, что это из-за того, что мы не учитываем, возможно важные, параметры. Такие, как: $idkey, $timestamp.
$timestamp нужно записать так: $timestamp = time();
$idkey нужно, наверное сначала загрузить страничку http://passport.yandex.ru/passport?mode=auth и узнать значение поля idkey.

йцукен 20.07.2010 в 15:21

ох спасибо тебе, добрый человек.
лучей щастья!

Ваш комментарий:


Я рекламные комменты не удаляю, но оно тут нафиг не нужно.