geekr
geekr copied to clipboard
Add user support
Need a following codes for sending user request:
Cookie: _csrf=value1
csrf-token: value2
Create a page where user can paste these values from a script, that is being executed on the main habr
page.
Да, авторизации действительно не хватает для комментарией и поиска по своей ленте
Login habr:
- Заходим по ссылке логина, где мы хотим авторизоваться https://habr.com/ru/auth/login/ Браузер отправляет GET https://habr.com/ru/auth/login/ HTTP/1.1 Получаем ответ:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Документ переехал!</title>
</head>
<body>
<a href="https%3A%2F%2Faccount.habr.com%2Flogin%2F%3Fstate%3D322c8679bd08d901ceeb7f0fd47fc551%26consumer%3Dhabr%26hl%3Dru_RU">https://account.habr.com/login/?state=322c8679bd08d901ceeb7f0fd47fc551&consumer=habr&hl=ru_RU</a>
</body>
</html>
Мы видим, что он генерирует ссылку с параметрами state, consumer. Нам нужен state Если перейти по https://account.habr.com/login/?state=322c8679bd08d901ceeb7f0fd47fc551&consumer=habr&hl=ru_RU то будет просто форма логина.
- Теперь я попытаюсь в эту web форму ввести свой логин пароль Передаем пост запрос с известными параметрами POST https://account.habr.com/ajax/login/ HTTP/1.1 http-referer https://account.habr.com/login/?state=322c8679bd08d901ceeb7f0fd47fc551&consumer=habr&hl=ru_RU
state: 322c8679bd08d901ceeb7f0fd47fc551
consumer: habr
email: [email protected]
password: MyLongPassword123
captcha:
g-recaptcha-response:
captcha_type: recaptcha
Получаем респонс со следующим содержимым:
window.location.href = 'https://habr.com/ac/entrance/?token=a122f063b00278fcd27f482616316513&state=322c8679bd08d901ceeb7f0fd47fc551&time=1604393689&sign=2bfe68e12b8ef4aadfe3649000fda975&utm_nooverride=1';
Если перейти по этой ссылке, то возвращается html документ:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Документ переехал!</title>
</head>
<body>
<a href="https%3A%2F%2Fhabr.com%2Fru%2F">https://habr.com/ru/</a>
</body>
</html>
Ну вот мы получили токен. token=a122f063b00278fcd27f482616316513
Комментарии к посту
POST https://habr.com/json/comment/ HTTP/1.1 http-referer https://habr.com/ru/post/526068/
ts: 1604393729
tt: 2
ti: 526068
comment_id: 0
parent_id: 0
text: Будем помогать проекту
action: add
Ответ в виде html файла с JavaScript скриптами
Но, допустим, я хочу изменить свою специальность - захожу в настройки аккаунта https://habr.com/ru/auth/settings/profile/ И меняю специальность, допустим, на python разработчик
POST https://habr.com/json/settings/profile/ HTTP/1.1
Host: | habr.com |
---|---|
Connection: | keep-alive |
Content-Length: | 92 |
Accept: | application/json, text/plain, / |
DNT: | 1 |
User-Agent: | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36 Edg/86.0.622.58 |
Content-Type: | application/x-www-form-urlencoded |
Origin: | https://habr.com |
Sec-Fetch-Site: | same-origin |
Sec-Fetch-Mode: | cors |
Sec-Fetch-Dest: | empty |
Referer: | https://habr.com/ru/auth/settings/profile/ |
Accept-Encoding: | gzip, deflate, br |
Accept-Language: | ru |
Cookie: | habrsession_id=habrsession_id_e7e33de3f0f541108140068a6d5c9cf0; hl=ru; fl=ru; _ga=GA1.2.1205135727.1604395784; _gid=GA1.2.757514714.1604395784; _ym_uid=16043957851020971966; _ym_d=1604395785; _ym_isad=2; _ym_visorc=w; PHPSESSID=5d87e9r2ivnqaek0oe4p8iq8ru; hsec_id=342d6cf32b4f55666f7a1b774bfcc84b; feed_flow=top; split201901=B; ab_test_vacancies_block_group=A; neuro-habr=ab92f052-ff7e-45a6-a005-fe1812dba9f1; _ym_visorc_24049213=b |
sex: 0
specializm: Python разработчик
По сути, всё работает через куки
Я пользуюсь endpoint'ом m.habr.com/kek/v{version}
для api запросов и там всё по-другому. Но тогда для юзера можно использовать десктопный habr.com/json
, чтобы использовать только один токен.
Спасибо, что подсказали!
@LencoDigitexer
Ну вот мы получили токен.
А как его использовать то? Ни token, ни sign параметры нигде не появляются на клиенте в запросах. Есть PHPSESSID, habrsession_id, hsec_id и все они не похожи на те значения, которые выдаёт habr.com/ac/entrance
Да, этот токен не очень важен. Прости за мусорное расследование, но я нашел новое. Оно основано на анализе опесорсного приложение хабра https://github.com/Makentoshe/Habrachan
Итак, авторизация.
POST https://habr.com/auth/o/access-token HTTP/1.1
Сервисные данные браузера
client: | 85cab69095196f3.89453480 |
---|---|
apiKey: | 173984950848a2d27c0cc1c76ccf3d6d3dc8255b |
Content-Type: | application/x-www-form-urlencoded |
Content-Length: | 161 |
Host: | habr.com |
Connection: | Keep-Alive |
Accept-Encoding: | gzip |
User-Agent: | okhttp/4.1.0 |
Тело POST запроса
email: [email protected]
password: MyLongPassword123
client_secret: 41ce71d623e04eab2cb8c00cf36bc14ec3aaf6d3
client_id: 85cab69095196f3.89453480
grant_type: password
Ответ сервера:
Server: | QRATOR |
---|---|
Date: | Wed, 04 Nov 2020 15:34:46 GMT |
Content-Type: | application/json |
Transfer-Encoding: | chunked |
Connection: | keep-alive |
Keep-Alive: | timeout=15 |
Vary: | Accept-Encoding |
Access-Control-Allow-Origin: | * |
X-Frame-Options: | SAMEORIGIN |
P3P: | CP="CAO DSP COR CURa ADMa DEVa PSAa PSDa IVAi IVDi CONi OUR OTRi IND PHY ONL UNI FIN COM NAV INT DEM STA" |
X-Content-Type-Options: | nosniff |
Content-Encoding: | gzip |
Strict-Transport-Security: | max-age=63072000; includeSubDomains; preload |
Public-Key-Pins: | pin-sha256="jWWta3ma1DSx8lFr6uv04x6sSRmK5X4Z0ivIL7+qKLM="; pin-sha256="Efde6ZPsmxzZkludmzwnp0QJhZ1mSwHrhDxczbpZcmM="; pin-sha256="klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY="; pin-sha256="kUh5F9diW5KlrhQ+nEKTIVFWVZuNbVqkKtm+KOGPXCE="; max-age=15552000 |
X-Proxy-Upstream: | habrcom-engine |
{
"access_token": "90f1c66b314a095a14f259aa4ac40f3d6d59babf",
"server_time": "2020-11-04T18:34:45+03:00"
}
Теперь на основе этих данных попробуем получить данные обо мне
GET https://habr.com/api/v1/users/me HTTP/1.1
Сервисные данные браузера
client: | 85cab69095196f3.89453480 |
---|---|
token: | 90f1c66b314a095a14f259aa4ac40f3d6d59babf |
Host: | habr.com |
Connection: | Keep-Alive |
Accept-Encoding: | gzip |
User-Agent: | okhttp/4.1.0 |
Ответ сервера:
{
"data": {
"avatar": "https://habr.com/images/avatars/stub-user-middle.gif",
"badges": [
{
"alias": "habred",
"description": "Пользователь с кармой >0",
"id": 1,
"is_disabled": false,
"is_removable": false,
"title": "Захабренный",
"url": null
}
],
"common_tags": [],
"contacts": [],
"counters": {
"comments": 7,
"favorites": 9,
"followed": 1,
"followers": 0,
"posts": 0
},
"fullname": null,
"geo": {
"city": null,
"country": null,
"region": null
},
"id": 2279184,
"is_can_vote": false,
"is_rc": true,
"is_readonly": false,
"is_subscribed": false,
"login": "LencoDigitexer",
"path": "/users/lencodigitexer/",
"rating": 0,
"rating_position": 0,
"score": 1,
"sex": 0,
"specializm": "Python разработчик",
"time_registered": "2020-02-07T18:04:28+03:00"
},
"server_time": "2020-11-04T18:34:46+03:00"
}
Вот здесь описан api Хабра
https://github.com/Perkovec/HabrApi/blob/96413ad10c28b5b4432aefb82fc70b63b519c3b2/README.md
Вот это уже круто!
Я же нашёл значения csrf-token, _csrf и connect_sid на фронте:
-
csrf-token берётся из
document.querySelector('meta[name="csrf-token"]').content
- _csrf и connect_sid берутся из куки. Вот только connect_sid через скрипт не получишь, там стоит HttpOnly флаг.
Можно просить пользователей заходить в DevTools и копировать значения в приложение, но мне ой как кажется, что это дико неудобно. Ваш метод гораздо легче.
Единственный вопрос - как брать client_id? Я нашёл, что https://m.habr.com/kek/v1/auth/habrahabr/?back=/ru/all/&hl=ru
редиректит на https://habr.com/ru/auth/o/login/
, где есть в параметрах этот client_id, но можно ли его по-другому вытащить?
UPD: смог получить те же данные из users/me
, подставляя как свой client_id, так и ваш. Похоже, серверу вообще плевать, что там стоит.
csrf-token берется отсюда. Вот...
https://m.habr.com/ru/sasasa/
Найти строку
<meta name="csrf-token" content="ccYo6XIK-Iv9i-0Nq7pTdx0YfjT0SzdV6-IA">
Мне кажется, client_id нужно получить, регистрируя своё приложение, так ведь?
От https://m.habr.com/kek/v1/auth/habrahabr
идёт редирект на https://habr.com/ru/auth/o/login
с такими параметрами, как state и client_id. Я бы брал отсюда client_id, но axios как-то хреново хандлит редиректы, поэтому походу будет просто легче взять какой-нибудь client_id, главное чтобы работало.
Мне кажется, client_id нужно получить, регистрируя своё приложение, так ведь?
И кто мне, собственно, разрешит такое делать? Для того, чтобы приложение одобрили, нужна ясная причина, а тут я просто хочу абузить их апи.
Ну раз это полулегально, то пусть client_id=85cab69095196f3.89453480 будет от HabraChan. А так, Вашу новость на хабре оценили и почему бы не попытаться достучаться до тех поддержки?
Уже написал, жду ответа.
Есть на примете ещё доки по API хабра для приложений? Потому что одних комментариев будет мало) К тому же, нигде эти пути не найти ни на мобильном, ни на десктопном сайте.
Думаю, тебе скинут документацию по api хабра. А так, вот несколько описаний api, что я смог найти: https://github.com/Perkovec/HabrApi https://github.com/Makentoshe/Habrachan/wiki
Здравствуйте! К сожалению, в данный момент доступ к нашему API не предоставляется. Мы планируем возобновить предоставление доступа после того как закончим доработку публичного API, но каких-либо точных дат у нас пока нет, т.к. в данный момент мы заняты решением других приоритетных задач.
Ожидаемо.
О, привет всем! Видел мой репо пинганули тут (чисто случайно). Какие именно описания вам нужны? Описания на вики там немного подтухли, бтв.
Если еще актуально, офк
Это победа!
Мне удалось сделать авторизацию через сайт мобильного API (habr.com/kek/v1/auth)!
@Makentoshe , сегодня выложу код на гитхаб, если надо. Тогда ты сможешь отказаться от поддержки старой версии API.
Единственный минус - все запросы для авторизации нужно делать с сервера (в том числе и получать csrf токен)
@jarvis394 Красиво, спасибо. У меня тоже кое какие наработки есть +- рабочие, но на андройд они ложатся не нативно, а через WebView(встроенный браузер с движком), т.к. для нативной реализации нужно проходить гуглокапчу, а без доступа к приватному ключу капчи нативно это по нормальному не сделать (через гугол либу для этого).
а без доступа к приватному ключу капчи нативно это по нормальному не сделать
Т.е. гкапчу, такую же, как на сайте account.habr.com, можно сделать (скорее скопировать) в браузере? Когда я делал авторизацию, я вообще про капчу забыл :p
Когда при тестах вылезала капча, я логинился на основном сайте и капча уходила.
@jarvis394 ага, она только в браузере и работает. Юзается v2reCAPTCHA. Можно с Fiddler'ом или Wireshark'ом побуриться, я там находил и апи ключ и прочее, как это у них работает на фронте. Я особо не web-developer, поэтому сильно сказать не могу, что там конкретно есть, и насколько полезно
Для андройда там нужно свой ключ отдельный генерировать и к тому же при генерации указывать application package приложения, ну т.е. вообще не вариант. Я в андройде генерировал уже готовенькую ссылку со всеми свистелками, показывал на webview дефолтную форму логина, а потом перехватывал response и вытаскивал нужные куки
сегодня выложу код на гитхаб
https://github.com/jarvis394/habra-auth/blob/main/src/index.ts
сегодня выложу код на гитхаб
https://github.com/jarvis394/habra-auth/blob/main/src/index.ts
Ну так то да, если в пароле не ошибаться, то капча вылезать не будет и все будет ок. Если хоть раз ошибиться, дальше сервер будет требовать g-recaptcha-response. А еще он может ее сбросить, если время истекло, там вроде секунд 30-60 примено, точно не помню, и надо будет новую запрашивать