Как проверить Cookie Token против bcrypt-хэшированного токена в БД при использовании Persistent Login Cookies?

В этом популярном решении для Persistent Login Cookies, которое включает в себя создание случайного 128-битного «токена» для сохранения в Cookie пользователя, Йенс Роланд рекомендует:

И НЕ УСТАНАВЛИВАЙТЕ ПОСТОЯННУЮ ЛОГИНУЮ КУХНИ (ТОКЕН) В ВАШЕЙ БАЗЕ ДАННЫХ, ТОЛЬКО ХАШ ЭТО! Маркер входа – это эквивалент пароля, поэтому, если злоумышленник получил доступ к вашей базе данных, он может использовать токены для входа в какую-либо учетную запись, точно так же, как если бы они были комбинациями паролей с открытым текстом. Поэтому при хранении постоянных токенов входа используйте сильное соленое хеширование (bcrypt / phpass).

Но как вы проверяете токен Cookie против bcrypted Token в БД, чтобы подтвердить, что вход в Cookie действителен, когда bcrypting Token Cookie всегда даст другой результат (так как bcrypting всегда использует случайную соль)?

Другими словами, вы не можете просто шифровать токен Cookie и искать совпадение в БД, так как вы его никогда не найдете, так как вы на самом деле сопоставляете его с хеш-версией в БД в соответствии с рекомендуемым решением («The сервер хранит таблицу number-> username association, которая проверяется на достоверность файла cookie. ")?

Редактировать:

Имейте в виду, что в соответствии с рекомендуемым решением, связанным выше, у одного пользователя может быть несколько Cookies / токенов для разных устройств. Я упоминаю об этом, потому что был отправлен ответ (который с тех пор был удален), который предположил, что это только один токен на пользователя.

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

При аутентификации «cookie cookie» «Запомнить меня» (который должен состоять из userid и token ) вам потребуется выполнить итерацию по каждой из записей маркера для этого идентификатора пользователя (обычно только одна запись, не более нескольких) и проверить каждый отдельно используя сохраненную случайную соль:

 foreach (entry in stored_tokens_for_user) { if (entry.hashed_token == bcrypt(cookie.token, entry.random_salt)) return true; } return false; 

(если ваша база данных имеет встроенную поддержку bcrypt как часть синтаксиса запроса, вы можете создать подготовленный оператор, чтобы сделать это за вас)