Буквально вчера была окончательно решена проблема перманентного логина в Андроид-приложении.
Краткое содержание предыдущих серий.
1. Немного суровой реальности. Браузер общается с сайтом при помощи так называемой "сессии", то есть некоего набора данных, признаваемого обеими сторонами. В какой-то момент сессия считается просроченной и все данные о контактах браузера с сервером обнуляются. Если, например, сервер подтвердил ввод пароля для данной сессии, то потеряв сессию браузер не сможет утверждать серверу, что он имеет право совершать действия от имени пользователя. Естественно, народ уже давно решил эту проблему при помощи всяких исхищрений. Одним из них, например, является хранение контекста (или токена для его восстановления) в памяти браузера (кукис или локальное хранилище)
2. Ещё более суровая реальность. До сих пор мои сайты и андроид-приложения эксплуатировали эту фичу без зазрения совести. В webView кукис сохраняются так же, как в обычном браузере, достаточно подключить нужную функцию в классе приложения. Но вот настали трудные времена и все внезапно озаботились приватностью. Откладывать кукисы, даже для упрощения логина, оказалось страшно опасным действием. Все сайты вняли требованиям возмущённых пользователей и начали требовать от них добровольно соглашаться на сию потерю анальной девственности. В частности, мои сайты были занесены в "красный список" сами-понимате-какой-корпорацией именно за отсутствие "консента". Пройдя унизительную процедуру я вернул сайтам честное имя, но пользователям от этого лучше не стало. Периодически у них выскакивают напоминания "этот сайт следит за тобой, нажми кнопку чтобы стать его рабом". Логин при этом мягко говоря про%бывается и пользователю приходится совершать дополнительные телодвижения для его восстановления (да, без ввода пароля, но всё равно геморрой).
Какова же альтернатива? Я подумал тут с Gemini, и мы пришли к выводу, что можно хранить токен не в памяти браузера, а в приложении, передавая его туда-сюда через адресную строку. Для десктопного браузера это неприемлемо, ведь тем самым мы позволяем пользователю сверкать у всех навидуголой жопой секретным токеном. Но для смартфона такой опасности нет. Адресная строка в приложении отсутствует, а значит всё, что там лежит остаётся между приложением и сервером. Короче, страничка логина принудительно получает от приложения дополнительный параметр, означающий "это мобильный клиент, ему - можно". При удачном логине сервер делает для такого клиента исключение. Он генерит этому пользователю персональный токен, запомнинает его вместе с датой выдачи и возвращает его в виде аргумента при перенаправлении на основную страницу. А поскольку основная страница тоже рендерится приложением, оно потихоньку считывает этот токен и запоминает его. Но запоминает уже не в виде богомерзкого кукиса, а в своей родненькой памяти, о которой никакой гугель-шмугель не знает, и знать не должОн. Если в следующий раз ему попадётся основная страничка, он пороется в своей памяти и, при наличии там токена, впрыснет его в адресную строку, чисто на всякий случай. В результате, основная страничка, подгружаемая в единожды залогиненом приложении, гарантированно получит токен. Всё, задачка решена, можно удалять код, откладывающий кукисы, а с ним заодно и консент-контент!
Ну и на дессерт: как я решил проблему пароля для регистрации и логина. Основной опасностью тут является хищение пароля всякими сниферами. Так вот, при моей схеме пароль тупо не передаётся на сторону сервера (и соответственно там его нет). Даже если вы сидите на канале пользователя и прорвались через HTTPS, то всё равно увидите только чек-сумму, да и то не самого пароля, а чего-то наложенного на ещё что-то. Как это работает? Очень просто. При регистрации в браузер посылается "соль" которой посыпается пароль. После этого результат (в виде чек-суммы) отправляется на сервер и там сохраняется. Каждая попытка логина сопровождается генерацией дополнительного секретного компонента (назовём его "перец"). Браузер накладывает на введённый пароль и "соль", и "перец" перед тем как вернуть результат на проверку. Сервер вытаскивает "посоленную" чек-сумму для данного пользователя, накладывает на неё индивидуальный "перец" и сравнивает результат с предъявленным браузером. Подделать или зареверсить эту схему практически невозможно.
Дополнительная "фишка" - защита от поддельного запроса на аутентикацию. Дело в том, что в роли "перца" выступает юникс-тайм на данный момент времени (со стороны сервера). Если кто-то вздумает повторить запрос на логин со старым "перцем", то сервер его отвергнет, так как он уже "просрочен" по сравнению с последним успешным логином. Единственной лазейкой является полная имитация всех алгоритмов на стороне браузера, плюс кража секретной чек-суммы пароля (что является фактически кражей самого пароля).
Краткое содержание предыдущих серий.
1. Немного суровой реальности. Браузер общается с сайтом при помощи так называемой "сессии", то есть некоего набора данных, признаваемого обеими сторонами. В какой-то момент сессия считается просроченной и все данные о контактах браузера с сервером обнуляются. Если, например, сервер подтвердил ввод пароля для данной сессии, то потеряв сессию браузер не сможет утверждать серверу, что он имеет право совершать действия от имени пользователя. Естественно, народ уже давно решил эту проблему при помощи всяких исхищрений. Одним из них, например, является хранение контекста (или токена для его восстановления) в памяти браузера (кукис или локальное хранилище)
2. Ещё более суровая реальность. До сих пор мои сайты и андроид-приложения эксплуатировали эту фичу без зазрения совести. В webView кукис сохраняются так же, как в обычном браузере, достаточно подключить нужную функцию в классе приложения. Но вот настали трудные времена и все внезапно озаботились приватностью. Откладывать кукисы, даже для упрощения логина, оказалось страшно опасным действием. Все сайты вняли требованиям возмущённых пользователей и начали требовать от них добровольно соглашаться на сию потерю анальной девственности. В частности, мои сайты были занесены в "красный список" сами-понимате-какой-корпорацией именно за отсутствие "консента". Пройдя унизительную процедуру я вернул сайтам честное имя, но пользователям от этого лучше не стало. Периодически у них выскакивают напоминания "этот сайт следит за тобой, нажми кнопку чтобы стать его рабом". Логин при этом мягко говоря про%бывается и пользователю приходится совершать дополнительные телодвижения для его восстановления (да, без ввода пароля, но всё равно геморрой).
Какова же альтернатива? Я подумал тут с Gemini, и мы пришли к выводу, что можно хранить токен не в памяти браузера, а в приложении, передавая его туда-сюда через адресную строку. Для десктопного браузера это неприемлемо, ведь тем самым мы позволяем пользователю сверкать у всех навиду
Ну и на дессерт: как я решил проблему пароля для регистрации и логина. Основной опасностью тут является хищение пароля всякими сниферами. Так вот, при моей схеме пароль тупо не передаётся на сторону сервера (и соответственно там его нет). Даже если вы сидите на канале пользователя и прорвались через HTTPS, то всё равно увидите только чек-сумму, да и то не самого пароля, а чего-то наложенного на ещё что-то. Как это работает? Очень просто. При регистрации в браузер посылается "соль" которой посыпается пароль. После этого результат (в виде чек-суммы) отправляется на сервер и там сохраняется. Каждая попытка логина сопровождается генерацией дополнительного секретного компонента (назовём его "перец"). Браузер накладывает на введённый пароль и "соль", и "перец" перед тем как вернуть результат на проверку. Сервер вытаскивает "посоленную" чек-сумму для данного пользователя, накладывает на неё индивидуальный "перец" и сравнивает результат с предъявленным браузером. Подделать или зареверсить эту схему практически невозможно.
Дополнительная "фишка" - защита от поддельного запроса на аутентикацию. Дело в том, что в роли "перца" выступает юникс-тайм на данный момент времени (со стороны сервера). Если кто-то вздумает повторить запрос на логин со старым "перцем", то сервер его отвергнет, так как он уже "просрочен" по сравнению с последним успешным логином. Единственной лазейкой является полная имитация всех алгоритмов на стороне браузера, плюс кража секретной чек-суммы пароля (что является фактически кражей самого пароля).
Tags: