Как защитить поле пароля в Mongoose / MongoDB, чтобы оно не возвращалось в запросе при заполнении коллекций?
Предположим, у меня есть две коллекции/схемы. Один из них-схема пользователей с полями имени пользователя и пароля, затем у меня есть схема блогов, которая имеет ссылку на схему пользователей в поле автора. Если я использую Мангуста, чтобы сделать что-то вроде
Blogs.findOne({...}).populate("user").exec()
У меня будет документ блога и пользователь заполнены тоже, но как я могу предотвратить Мангуст/MongoDB от возврата поля пароля? Поле пароля хэшируется, но оно не должно быть возвращено.
Я знаю, что могу опустить поле пароля и возвращает остальные поля в простом запросе, но как это сделать с помощью заполнения. Кроме того, есть ли элегантный способ сделать это?
кроме того, в некоторых ситуациях мне нужно сделать поле пароля, например, когда пользователь хочет войти в систему и изменить пароль.
10 ответов:
.populate('user' , '-password')http://mongoosejs.com/docs/populate.html
JohnnyHKs ответ с использованием параметров схемы, вероятно,путь сюда.
также обратите внимание, что
query.exclude()существует только в 2.х филиал.
вы можете изменить поведение по умолчанию на уровне определения схемы с помощью
selectполя:password: { type: String, select: false }затем вы можете вытащить его в
findиpopulateвызовы через выбор поля как'+password'. Например:Users.findOne({_id: id}).select('+password').exec(...);
Edit:
попробовав оба подхода, я обнаружил, что подход exclude always не работал для меня по какой-то причине, используя стратегию passport-local, на самом деле не знаю, почему.
Итак, вот что я в конечном итоге с помощью:
Blogs.findOne({_id: id}) .populate("user", "-password -someOtherField -AnotherField") .populate("comments.items.user") .exec(function(error, result) { if(error) handleError(error); callback(error, result); });нет ничего плохого в исключении всегда подход, он просто не работал с паспортом по какой-то причине, мои тесты сказали мне, что на самом деле пароль был исключен / включен, когда я хотел. Единственная проблема с включить всегда подход заключается в том, что мне в основном нужно пройти через каждый вызов, который я делаю в базу данных, и исключить пароль, который является большой работой.
после пары ответов я узнал, что есть два способа сделать это, "всегда включать и исключать иногда" и "всегда исключать и включать иногда"?
пример как:
включить всегда, но иногда исключить пример:
Users.find().select("-password")или
Users.find().exclude("password")exlucde всегда, но иногда включают пример:
Users.find().select("+password")но вы должны определить в схеме:
password: { type: String, select: false }
User.find().select('-password')Это правильный ответ. Вы не можете добавитьselect: falseна схему, так как он не будет работать, если вы хотите войти.
предполагая, что ваше поле пароля - это "пароль", вы можете просто сделать:
.exclude('password')есть более обширный пример здесь
это сосредоточено на комментариях, но это тот же принцип в игре.
это то же самое, что использовать проекцию в запросе в MongoDB и передавать
{"password" : 0}в поле проекция. Смотрите здесь
вы можете добиться этого, используя схему, например:
const UserSchema = new Schema({/* */}) UserSchema.set('toJSON', { transform: function(doc, ret, opt) { delete ret['password'] return ret } }) const User = mongoose.model('User', UserSchema) User.findOne() // This should return an object excluding the password field
решение состоит в том, чтобы никогда не хранить пароли открытого текста. Вы должны использовать пакет, как
[bcrypt]1 или[password-hash]2.пример использования для хэширования пароля:
var passwordHash = require('password-hash'); var hashedPassword = passwordHash.generate('password123'); console.log(hashedPassword); // sha1I7HRwy7$cbfdac6008f9cab4083784cbd1874f76618d2a97пример использования для проверки пароля:
var passwordHash = require('./lib/password-hash'); var hashedPassword = 'sha1I7HRwy7$cbfdac6008f9cab4083784cbd1874f76618d2a97'; console.log(passwordHash.verify('password123', hashedPassword)); // true console.log(passwordHash.verify('Password0', hashedPassword)); // false
Это скорее следствие к исходному вопросу, но это был вопрос, с которым я столкнулся, пытаясь решить мою проблему...
а именно, как отправить пользователя обратно клиенту в Пользователь.сохранить () обратный вызов без поля пароля.
Use case: пользователь приложения обновляет информацию о своем профиле / настройки из клиента (пароль, контактная информация, whatevs). Вы хотите отправить обновленную информацию о пользователе обратно клиенту в ответе, как только он успешно сохранен в mongoDB.
User.findById(userId, function (err, user) { // err handling user.propToUpdate = updateValue; user.save(function(err) { // err handling /** * convert the user document to a JavaScript object with the * mongoose Document's toObject() method, * then create a new object without the password property... * easiest way is lodash's _.omit function if you're using lodash */ var sanitizedUser = _.omit(user.toObject(), 'password'); return res.status(201).send(sanitizedUser); }); });
при использовании
password: { type: String, select: false }вы должны иметь в виду, что он также будет исключать пароль, когда нам это нужно для аутентификации. Так что будьте готовы справиться с этим, как вы хотите.
Comments