За последние 24 часа нас посетили 46624 программиста и 1728 роботов. Сейчас ищут 593 программиста ...

Логика работы с чек-боксом "Запомнить меня"

Тема в разделе "PHP для новичков", создана пользователем bocharsky, 25 дек 2014.

  1. bocharsky

    bocharsky Новичок

    С нами с:
    18 апр 2014
    Сообщения:
    77
    Симпатии:
    1
    Подскажите, как правильно организовать обработку чек-бокса "Запомнить меня" в форме авторизации.

    Общая логика, основанная на куки, в моем представлении такая (надеюсь, в целом верная):

    1. Пользователь заходит на страницу.
    2. В этот момент браузер проверяет, есть ли для этого сайта кука.
    3. Я проверяю, установлена ли нужная кука
    if( isset($_COOKIE['remember_me'] ) {
    4. Если да, извлекаю куку, добываю из нее информацию для авторизации,
    подставляю в форму. И устанавливаю чекбокс.
    Пользователь видит флажок, видит данные в полях, ему остается только нажать кнопку Войти.
    5. Если кук нет, поля остаются пустыми, чек-бокс остается пустой, пользователь лично вводит логин и пароль, нажимает на кнопку "Войти", я записываю в сессию флаг "авторизован". И если он установил чекбокс, то устанавливаю куку. Если он оставил чекбокс пустой - не записываю куку.

    Надеюсь, я все верно изложил.

    Вот чего я не понимаю:

    Когда пользователь нажимает на кнопку "Войти" (не важно, сам он ввел данные, или они автоподставились из куки), я должен проверить, есть ли галочка "Запомнить мня", или нет. Вдруг она была, но он ее снял. Или не было, а он поставил.
    Если галочки нет, то я ничего в куки не пишу и, наверное, даже на всякий случай их убиваю.
    Если галочка есть, то я куки записываю.
    Типичный кейс: пользователь поставил галочку "Запомнить меня" и год ходит с ней.
    Получается, что я каждый раз перезаписываю куки, увидя галочку. Не зависимо от того поставил ее пользователь сейчас, или она и так была установлена.

    Вот то, что я постоянно их перезаписываю, меня смущает.

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

    Подскажите оптимальную логику этого процесса.

    Спасибо!
     
  2. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
    Лучше используй сессии, когда пользователь устанавливает чекбокс запомнить меня, просто жизнь сессии ставь месяц например
     
  3. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    галочка "запомнить меня" не должна меня доставать формами. пусть каждое мое посещение сайта сайт меня узнаёт и начинает мою сессию автоматом. на то оно и "запомни меня". оно не логин-пароль должно запомнить а привязять некоторую куку у меня с некоторым уникальным значением у себя. и когда я вхожу с этой кукой и если еще есть моя уникальная пара - начинается мой сеанс. понятно объясняю?

    соответственно если я хочу чтоб меня забыли - я просто делаю "выход". на это сайт обязан забыть мою текущую сессию, куку в этом браузере и встречное значение к этой куке. напомню что в современности я могу хоть с сотни устройств заходить. и все должны иметь возможность "запомнить" меня на сайте. то есть сайт не должен хранить только одно уникальное значение.
     
  4. bocharsky

    bocharsky Новичок

    С нами с:
    18 апр 2014
    Сообщения:
    77
    Симпатии:
    1
    Круто! Спасибо!
    А) Об этом я даже и не думал
    Б) Это действительно снимает мой вопрос про чекбокс ))

    Спасибо!
     
  5. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    но ты чекбокс-то не забудь. не все желают чтоб сайт их автоматом узнавал. но логика запоминания должна быть именно такой - раз я уже когда-то ткнул в этом браузере то сайт должен меня узнавать и не показывать формы авторизации
     
  6. bocharsky

    bocharsky Новичок

    С нами с:
    18 апр 2014
    Сообщения:
    77
    Симпатии:
    1
    Вот про это хочу спросить.

    А как обойтись только одним значением?
    Я предполагал поступить так:
    Записывать две куки. Одна - логин (у меня используется имейл). Вторая - хэш на основе пароля. Насколько я понял по заметкам в интернете, рекомендуют добавлять к нему некие параметры персонализации, скажем, тип ОС, расширение экрана и пр.
    Значит, делаю что-то вроде md5($password.$screen.$browser), записываю в куку.

    Когда пользователь заходит на сайт, я беру куку с логином и ищу для нее в базе пароль.

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

    т.е. if ($_COOKIE['remember_me'] == md5($password_from_bd.$screen.$browser) {

    Это я понимаю)

    А как обойтись только одной кукой - нет. Как мне понять, с чем именно сравнивать куку? Всю БД перебирать?

    Подскажите, плиз.
     
  7. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
    Смотри есть сессии.
    Пользователь авторизовался и ты в сессию записал его id из базы и ip
    Когда пользователь заходит и у него есть сессия и в ней id и ip совпадает, значит этот наш пользователь, так как только тот кто авторизовался получает в сессию id и ip.
     
  8. bocharsky

    bocharsky Новичок

    С нами с:
    18 апр 2014
    Сообщения:
    77
    Симпатии:
    1
    Сессии не работают после того, как пользователь закрыл браузер.
    Как поддерживать состояние при переходах между страницами понятно.
    Вопрос про реализацию стандартной фичи "запомнить меня" - чекбокс в форме авторизации. При установке которого, сайт "узнает" пользователя при любом новом заходе.
    Тут (могу конечно ошибаться) сессии бессильны.

    Но все равно спасибо за желание помочь!
     
  9. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
    Михаил Запаленов нравится это.
  10. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Лучше галка "чужой компьютер" типа не запоминай меня
     
  11. bocharsky

    bocharsky Новичок

    С нами с:
    18 апр 2014
    Сообщения:
    77
    Симпатии:
    1
    Не знал про это. Спасибо. Буду изучать

    Добавлено спустя 48 секунд:
    Спасибо за идею. Упустил из виду.

    Добавлено спустя 58 секунд:
    Вычитал еще такой подход:
    При генерации куки создается (просто от фонаря) уникальный хэш и пишется юзеру в БД.
    Если у пользователя обнаруживается кука для данного сайта, из нее извлекается хэш и ищется в БД. Если находим - авторизуем пользователя.

    Вы это имели в виду?

    Но тогда непонятно зачем нужна новая сущность "хэш", если в БД уже хранится хэш пароля. Причем тоже сложновыдуманный: с солью и пр.

    Можно тогда в куку просто хэш пароля писать. Все равно в такой концепции хэш пароля и хэш этого уникального идентификатора для куки становятся равнозначными сущностями.

    Итого два вопроса:
    1. правильно ли я понял вашу мысль про "одну куку"
    2. чем генерация новой сущности - хэша для куки - лучше, чем использование уже существуюещего хэша пароля

    Спасибо!
     
  12. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    хэш пароля это хэш пароля. это нужно чтоб можно было авторизовать пользователя по введенному им паролю.

    когда он авторизовался на сайте - у него начался сеанс работы. этот сеанс нам как-то надо идентифицировать, правильно? для этого достаточно сессионной куки. итак у нас уже помимо таблицы пользователей появилась некоторая таблица сеансов. юзер может зайти с нескольких компов следовательно саму сущность "Юзер" мы уникально идентифицируем но сеансов у него может быть N.

    если юзер жмакнул "меня помни" то у нас появилась такая сессия для данного пользователя-браузера, которую мы должны помнить достаточно долго. это можно сделать той же таблицей сеансов, просто добавив какой-то признак перманентных сеансов, а можно отдельной таблицей запомненых сеансов.

    нет единого канонического подхода. каждый проект для себя сам решает что и как.
     
  13. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Мой вариант:
    - есть авторизационная кука
    - галка "запомни меня" (или "забудь меня", как предложил vs) рулит временем жизни этой куки.
    Всё!
     
  14. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    А что в этой куке?
     
  15. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    логин+пароль (сркзм)
     
  16. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Ну правда
     
  17. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
    Думаю там идентификатор сессии
     
  18. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    так сессия ж умрёт минут через двадцать.
     
  19. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
    glorsh66 нравится это.
  20. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    а нах увеличивать время жизни сессии? если человек более 20 минут отсутствует на сайте - как можно считать что его текущая сессия продолжается?
     
  21. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
    Чтобы его авторизовать когда он вернется если он это указал при входе.
     
  22. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    и для этого сессию увеличивать??????????????????? ты запутался. сессия это некоторые оперативные данные (назовём это для различия) сеанса. проипался юзверь на полчаса - чистим его останки. вернулся - начали новую сессию.
    с момента авторизации начинается сеанс. сеанс в свою очередь может запоминаться на время большее чем время жизни сессии. в том числе и до условной бесконечности если юзер нас об этом просит. вернулся пользователь с активным сеансом но протухшей сессией - начали для него новую сессию.
     
  23. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
    Да недопонимание в терминологии, ты прав
     
  24. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    А что ж в куке-то хранить?
     
  25. bocharsky

    bocharsky Новичок

    С нами с:
    18 апр 2014
    Сообщения:
    77
    Симпатии:
    1
    Тааак… это лишь добавляет новых вопросов:

    1. А зачем хранить сессии (видимо, идентификатор сессии) в БД?
    Как я понимаю ситуацию: сессии нужны, чтобы сохранять состояние при переходе между страницами. Чтобы не заставлять пользователя логиниться на каждой.

    Когда пользователь логинится, я сохраняю в сессию
    - флаг isLogged (он проверяется, чтобы давать доступ к страницам под логином)
    - роль (у меня разные типы пользователей, чтобы знать, какую менюшку вывести)
    - имейл (это у меня уникальный идентификатор, вместо логина. По нему я вытаскиваю из БД нужную для пользователя инфу для данной странице)

    Зачем мне записывать в БД идентификатор сессии? Что мне с ним потом делать?

    ….подозреваю, что дело в какой-то схеме защиты сессии от взлома… Поясните, плиз


    2. Запоминание пользователя для нескольких устройств.

    Окей, на каждом устройстве, включая разные браузеры оставлены куки. В них, насколько я понимаю, разные «хэши» (идентификаторы). Дальше надо записать в БД разное количество идентификаторов для каждого пользователя.
    Значит, сделать это в таблице User, создавая новые столбцы, не получится. У этого – 3, у этого – 5, и количество неизвестно.
    Наверное, надо создавать новую таблицу с полями типа user_id и user_hash и писать туда подряд. Типа

    user_id user_hash
    1 1234445
    1 3455654
    2 3534534
    3 3454546
    1 3454545

    Так?



    3. Если я просто генерю какой-то хэш, записываю его в куку и сохраняю в БД, то, насколько я понимаю, есть риск, что «хакер» украдет ее, поставит себе и все.

    Поэтому в Интернетах пишут, что надо не просто генерить какую-то длинную случайную строку. А смешивать пользовательские данные с параметрами системы, а потом их воспроизводить при проверке.
    Типа md5($login.$screen.$user_agent)

    Но тогда я не понимаю, как обойтись одной кукой.

    Как я бы сейчас сделал:
    Есть кука с логином (или уникальным хэшем), короче какой-то идентификатор.
    При заходе на страницу, мы ее извлекаем и ищем в базе. Нашли. Берем для этого пользователя его логин, а из его окружения – расширение экрана и юзер агент. Складываем в $login.$screen.$user_agent и сверяем со второй кукой, в которой лежит та же записанная комбинация, сделанная при установке куки

    Но меня смущает то, что в интернетах гуры пишут, что «кука должна быть одна». Т.е. они эту схему решают одной кукой. Как?

    Прошу прощения, если вам кажется, что вы уже мне все это разъяснили своими ответами)))))
    Буду признателен прояснению ситуации

    Спасибо!