Настройка
Я делаю авторизацию веб-сайта и хочу внедрить в него лучшие практики, сохраняя при этом код чистым и читабельным. На данный момент у меня есть классический код, подобный этому:
let foundUser = await userModel.findOne({ email: recievedEmail });
if(!foundUser)
error("not authorized!");
const isPasswordMatch = await bcrypt.compare(recievedPassword, foundUser.password);
if(!isPasswordMatch)
error("not authorized!");
foundUser.update({ $set: { lastLogin: new Date() }, $push: { myEvents: authEvent } });
foundUser.save();
success("authorized OK!");
Тем временем я задал вопрос о лучшей команде mongoose для выполнения auth , и мы создали следующую команду «auth-check-and-update» в «atomic» Способ:
const foundUser = await userModel.findOneAndUpdate(
{ email: recievedEmail, password: recievedPassword },
{ $set: { lastLogin: new Date() }, $push: { myEvents: authEvent } }
);
if(foundUser)
success("authorized OK!");
else
error("not authorized!");
Идея здесь очевидна - если пользователь с соответствующим адресом электронной почты и паролем найден , то пользователь считается авторизованным , а его отметка времени последнего входа в систему обновляется (одновременно).
Задача
Чтобы объединить лучшие практики из двух вышеперечисленных, мне нужно как-то встроить bcrypt.compare()
call в findOneAndUpdate()
call. Это сложно сделать, потому что я не могу просто "сравнить хешированные пароли"; bcrypt просто отличается от простых хэшей (например, sha или md5): Из соображений безопасности каждый раз возвращает разные хэши . (Ответы в ссылке объясняют «почему и как»).
Решение Попытка
Я посмотрел на mongoose-bcrypt
пакет: он использует Schema.pre()
функциональность:
schema.pre('update', preUpdate);
schema.pre('findOneAndUpdate', preUpdate);
Чтобы понять, пожалуйста, взгляните на mongoose-bcrypt\index.js
.
Вы увидите, что preUpdate
влияет только на создание нового пользователя (.. andUpdate
часть), но не на фактическую проверку (findOne
.. часть). Таким образом, этот плагин может подходить для реализации «регистрация пользователя» / «изменить пароль». Но он не может работать для авторизации предлагаемым способом.
Вопрос
Как бы вы "комбинировали" bcrypt.compare()
и userModel.findOneAndUpdate()
звонки при таких обстоятельствах?