Условия гонки для постоянных "Запомнить меня" печенье - PullRequest
6 голосов
/ 10 мая 2011

Согласно рекомендациям Постоянных файлов cookie для входа в систему , вы никогда не должны позволять использовать токен "Запомнить меня" более одного раза:

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

Затем, как вы справляетесь с состоянием гонки, когда пользователь одновременно посещает несколько URL-адресов на вашем сайте? У меня сейчас действительно есть эта проблема.

Скажем, двазапросы отправляются из браузера на сервер одновременно.Запросы не содержат сессионные куки, но те же куки "запомнить меня".Один из запросов будет обработан раньше другого и получит ответ с аутентифицированным файлом cookie сеанса и сгенерированным файлом cookie «Помни меня».

Токен «Помни меня» во втором запросе:теперь аннулирован , и на сервере генерируется другой идентификатор сеанса.Этот запрос не выполняется, поскольку пользователь не может быть аутентифицирован.

Я предложил несколько возможных решений, но ни одно из них не кажется очень хорошим.Я что-то упустил?

Ответы [ 2 ]

2 голосов
/ 26 июля 2013

Старый вопрос, но я нигде не нашел ответа. У меня такая же проблема. Мое решение состояло в том, чтобы сохранить старый токен в базе данных и использовать его как запасной вариант, если основной токен не найден. Но я убедился, что старый токен действителен только в течение короткого периода времени, например, через несколько секунд после смены токена. Тогда я изменяю токен только в том случае, если с момента предыдущего обновления прошло некоторое время, иначе будут случаи, когда токен будет меняться несколько раз подряд.

1 голос
/ 12 апреля 2014

Чтобы уточнить ответ Вангоса, я бы добавил, что нужно также использовать какой-то механизм блокировки.Рассмотрите этот псевдокод PHP-ish здесь:

if (isFallback($token)) {
  // Log the user in
} else {
  // Usual processing
  // If token has to be updated, save old token as fallback for a few seconds
}

Когда есть параллельные запросы, они могут оба оказаться в ветви else, один запрос вызовет обновление, а другой вызовет аннулирование токена.Я решил это путем использования именованного замка, названного в честь рассматриваемого $token, чтобы обернуть ветвь else.Кроме того, все одновременные запросы, кроме одного, не смогут получить блокировку, и в этом случае мы немного поспим и повторим попытку (после повторной попытки мы обнаружим, что токен стал резервным токеном).

if (isFallback($token)) {
  // Log the user in
} else {
  $couldLock = lock($token);
  if (!$couldLock) {
    usleep(10000);
    // Retry, possibly a recursive call
  } else {
    // Usual processing
    // If token has to be updated, save old token as fallback for a few seconds
    unlock($token);
  }
}

Я надеюсьэти соображения могут быть полезны.

...