Предыстория: Недавно мне понадобилось авторизоваться вконтакте программно. Я попробовал, но потом началась сессия... И так не закончил. Но вот теперь я закрыл сессию на стипендию. Да, поздравьте меня ! И решил закончить это дело. Цель: Получить доступ к персональной части страницы vkontakte.ru. То есть заиметь злой rmixsid! Кто пробовал, тот поймет. Примечание: Статья объясняет принцип авторизации, я не выкладываю готовый код, или программу, в этом нет смысла. Кто понимает в программировании, тот сможет это сделать и на Delphi и на C++. Тем кому не понятны слова, прошу на этот замечательный СЕКРЕТНЫЙ сайт, о котором не знают новички! Я вам раскрываю секрет откуда черпают знания трУхАцкЕры. _http://google.com/ Что использовал я? Среда разработки:--------------------Delphi 7 Язык программирования:--------------Object Pascal Библиотека для протокола HTTP:------Indy 10 Библиотека для парсинга текста:-----TRegExpr Сниффер:----------------------------HTTP Analyzer V5 И так приступим! Let's go! Let's Rock! Разобрав что и как, я выяснил. Браузер отправляет 2 пост запроса. При этом данные передаваемые серверу одинаковые всегда для одного и того же пользователя. Копнув глубже я увидел, что в куках сидит remixsid. Он же ведь где то генерируется? Да. Это происходит после первого пост запроса. Сервер редиректид браузер на другую страницу, пустую, но в коде java скрипт. В скрипте генерятся куки. Поскольку Indy не захотела скачать этот скрипт. Я решил не заморачиватся. Ведь есть простой путь. Пройти авторизацию на мобильной версии вконтакте. А потом добавить куки, и получить доступ к полноценной. Авторизация мобильной версии проходит тоже в два пост запроса. Первый очень простой, нам следует передать только два параметра: Code: email=vas9@host.domen pass=qwerty Где email - мыло пользователя, pass - пароль(и дураку понятно). В ответе приходит "мНогАбУкФ". Например: Как мы сдесь видим, нас интересуют несколько параметров. Каждый из них имеет свой "name" и "value". Что бы спарсить их я использовал следующую функцию: Code: function AuthPars(rStr: string): string; var rExp: TRegExpr; begin try rExp:= TRegExpr.Create; rExp.Expression:= 'name=\''(.*?)\''\svalue=\''(.*?)\'''; if rExp.Exec(rStr) then begin [COLOR=Red] http.Request.CustomHeaders.Add('Cookie: remixsid='+rExp.Match[2]); //Описание этой строки ниже[/COLOR] repeat Result:= Result + rExp.Match[1] + '=' + rExp.Match[2] + #13#10; until not rExp.ExecNext; end; finally rExp.Free; end; Зачем же я добавил в CustomHeaders remixsid? А что бы мы смогли после авторизации на m.vkontakte.ru, зайти на любую страницу полной версии. А вот как примерно должна выглядеть функция авторизации: Code: function AuthVK(login, pass: string): string; var s: TStringList; Astr: string; begin try s:= TStringList.Create; s.Add('email='+login); s.Add('pass='+pass); http.HandleRedirects:= true; Astr:= http.Post('http://login.vk.com/?act=login&to=&from_host=m.vkontakte.ru&pda=1', s); s.Clear; s.Text:= AuthPars(Astr); //Функция парсинга Result:= http.Post('http://m.vkontakte.ru/login', s); finally s.Free; end; end; Вот собственно и все. Для особо продвиннутых, пищущих на сокетах, не обязательно авторизоваться сначала на мобильной версии. Вы можете сразу в ответе первого пост запроса распарсить значения и передавать их потом как кукисы. УДАЧИ! P.S. Тему создал для уменьшения количества вопросов по поводу авторизации вконтакте. Я думаю новичкам теперь не создаст трудностей разобраться что и как.
Я все понимаю, для новичков, но для создания отдельной темы материал точно не тянет). Немного об авторизации, ты же не раскрыл тему сисек, одна капча и авторизации не будет. Привел бы несколько методов(способов), выбрал бы лучший, доказал бы почему так. Да, конечно, ты бы убил втрое больше времени, а может и того больше, но всегда было интересно читать исследование, то есть, взгляд изнутри! Тут все также как мы видим), попробуй дополнить, по фантазируй, а то так то нет смысла в отдельной теме... p.s. вот накидал на пайтоне: Code: def Logins(Login = "", Password = "", cookies = ""): cook = cookielib.CookieJar() opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cook)) datas = { 'act':'login', 'q':'1', 'al_frame':'1', 'expire':"", "captcha_sid":"", "captcha_key":"", "from_host":"vkontakte.ru", "email":Login, "pass":Password } headers = { "User-Agent":"Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9.2.6) Gecko/20100628 Ubuntu/10.04 (lucid) Firefox/3.6.6", "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Keep-Alive": "115", "Connection":"keep-alive" } params = urllib.urlencode(datas) req = urllib2.Request('http://login.vk.com/?act=login',params,headers) page = urllib2.urlopen(req).read() print page в page будет результат страницы после авторизации.
Это пи**ец ребята ТС, зачем использовать регулярки, если можно было сделать так: Code: Cookie := Copy(Buff, Pos('value=', Buff) + 7, 56); Cookie := 'remixsid=' + Cookie + ';'; Представляю сколько ещё ТС будет секасатся с капчей.
HakaR, регулярки куда удобней, т.к. результата по каким ниб причинам может быть не совсем тот что надо, и поэтому у тебя в Cookie будет вся страница =) а в регулярке после парсинга достаточно проверить reg.match[N] на присуствие симвлов, и уже считай все работает.
2 dirtybiz и где тут cURL ? в адресной строке обозревателя: Code: javascript: alert(document.cookie); хе-хе
NekitoSP, данным кодом, пользуюсь уже много времени. Ещё не разу не подводил. Конечно, если во всем проекте используются регулярки, то можно и в функции авторизации ипользовать. Но в том примитивном коде, который написал ТС, хватило бы и моего варианта (заодно исходник сократился бы на N строк и бинарник на N килобайт).
Регулярки намного проигрывают стандартным функциям pos, copy, delete по времени? Просто не привык использовать регулярные выражения. Это может быть и удобно, но думаю, у них есть и свои минуса.
HakaR Я очень рад, что вы меня критикуете. Но увы, ТС сам ламер. Поэтому и статья для таких же . Так что сильно не заморачивайтесь. Код который я привел, это не программа. А просто пример. P.S. Как только ТС продвинет свои ламерские знания дальше, родится новая и более продвинутая статья .
у мя пишет мол пасс неверный еще на первом запросе хотя всё верный Code: private void button1_Click(object sender, EventArgs e) { CookieContainer cooka = new CookieContainer(); richTextBox1.Text = PostRequest("http://login.vk.com/?act=login&to=&from_host=m.vkontakte.ru&pda=1", "email=правильное мыло%40mail.ru&pass=pass", "http://m.vkontakte.ru/login", cooka); } public string PostRequest(string url, string query, string referer,CookieContainer cookies) { byte[] postRequest = Encoding.Unicode.GetBytes(query); HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); request.Method = "POST"; request.AllowAutoRedirect = true; request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; request.Headers.Add("Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7"); request.Headers.Add("Accept-Encoding: gzip,deflate"); request.Headers.Add("Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3"); request.UserAgent = UserAgent(); request.ContentLength = postRequest.Length; request.ContentType = "application/x-www-form-urlencoded"; request.Referer = referer; request.CookieContainer = cookies; request.AutomaticDecompression = DecompressionMethods.GZip; Stream stream = request.GetRequestStream(); stream.Write(postRequest, 0, postRequest.Length); string data = string.Empty; using (StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream()/*, Encoding.GetEncoding(1251)*/)) { data = reader.ReadToEnd(); reader.Close(); } return data; }
P.S. Насчёт регулярных выражений. Для выделения строки, между двумя строками, я написал расширяющий метод. По мне, так это наилучший вариант. Пример использования: content.Substring("name='s' value='", "'"); // Получаем sid. Код расширяющего метода (без проверки ошибок параметров): public static string Substring(this string str, string left, string right) { int leftPos = str.IndexOf(left); if (leftPos == -1) { return string.Empty; } int startIndex = leftPos + left.Length; int rightPos = str.IndexOf(right, startIndex); if (rightPos == -1) { return string.Empty; } int length = rightPos - startIndex; return str.Substring(startIndex, length); } Данный код не сложно перевести на другие ЯП.
http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags Почитайте первый ответ
HtmlAgilityPack. Он конечно медленнее, вместо 0.0000001 сек. (для быстрого кода X-rus) он потратит целых 0.00001 сек. (цифры примерные но смысл понятен). Зато если контакт поменяет местами атрибуты name и value, смысл html не изменится, а вот регулярки и прочие парсеры работать не будут.