Предположим, у меня есть две коллекции / схемы. Один из них - это схема пользователей с полями имени пользователя и пароля, а затем у меня есть схема блогов, которая имеет ссылку на схему пользователей в поле автора. Если я использую Mongoose для чего-то вроде
Blogs.findOne({...}).populate("user").exec()
У меня будет документ блога и пользователь, но как мне запретить Mongoose / MongoDB возвращать поле пароля? Поле пароля хешировано, но не должно возвращаться.
Я знаю, что могу опустить поле пароля и вернуть остальные поля в простом запросе, но как мне это сделать с помощью populate. Кроме того, есть ли какой-нибудь элегантный способ сделать это?
Кроме того, в некоторых ситуациях мне нужно получить поле пароля, например, когда пользователь хочет войти в систему или изменить пароль.
Ответы:
.populate('user' , '-password')
http://mongoosejs.com/docs/populate.html
Ответ JohnnyHK с использованием параметров схемы - это, вероятно, путь сюда.
Также обратите внимание, что
query.exclude()
существует только в ветке 2.x.источник
Вы можете изменить поведение по умолчанию на уровне определения схемы, используя
select
атрибут поля:password: { type: String, select: false }
Затем вы можете втягивать его по мере необходимости
find
иpopulate
вызывать через выбор поля как'+password'
. Например:Users.findOne({_id: id}).select('+password').exec(...);
источник
Редактировать:
Попробовав оба подхода, я обнаружил, что подход «исключать всегда» не работает для меня по какой-то причине с использованием стратегии локального паспорта, действительно не знаю почему.
Итак, вот что я в итоге использовал:
Blogs.findOne({_id: id}) .populate("user", "-password -someOtherField -AnotherField") .populate("comments.items.user") .exec(function(error, result) { if(error) handleError(error); callback(error, result); });
Нет ничего плохого в подходе exclude always, он просто не работал с паспортом по какой-то причине, мои тесты показали мне, что на самом деле пароль был исключен / включен, когда я хотел. Единственная проблема с подходом include always заключается в том, что мне в основном нужно проходить каждый вызов, который я делаю в базе данных, и исключать пароль, что требует много работы.
После пары отличных ответов я обнаружил, что есть два способа сделать это: «всегда включать и иногда исключать» и «всегда исключать и иногда включать»?
Пример того и другого:
Пример включения всегда, но иногда исключения :
Users.find().select("-password")
или же
Users.find().exclude("password")
Исключение всегда, но иногда включает пример:
Users.find().select("+password")
но вы должны определить в схеме:
password: { type: String, select: false }
источник
.select("+field")
это приносит только то поле, которое я хочу__id
, хотя и.select("-field")
хорошо исключает,select: false
это обязательноUser.find().select('-password')
это правильный ответ. Вы не можете добавитьselect: false
схему, так как она не будет работать, если вы захотите войти в систему.источник
const query = model.findOne({ username }).select("+password");
и использовать это на маршрутах смены / сброса логина и пароля и в противном случае гарантировать, что он никогда не появится. Это намного безопаснее, чтобы он не возвращался по умолчанию, поскольку люди, как доказано, совершают ошибки, imoВы можете добиться этого, используя схему, например:
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
источник
Я использую для скрытия поля пароля в моем ответе REST JSON
UserSchema.methods.toJSON = function() { var obj = this.toObject(); //or var obj = this; delete obj.password; return obj; } module.exports = mongoose.model('User', UserSchema);
источник
Предполагая, что ваше поле пароля - «пароль», вы можете просто сделать:
.exclude('password')
Существует более обширный пример здесь
Это сосредоточено на комментариях, но в игре действует тот же принцип.
Это то же самое, что использовать проекцию в запросе в MongoDB и передать
{"password" : 0}
поле проекции. Смотрите здесьисточник
Blogs.findOne({ _id: id }, { "password": 0 }).populate("user").exec()
источник
Решение - никогда не хранить пароли в виде открытого текста. Вам следует использовать такой пакет, как bcrypt или password-hash .
Пример использования для хеширования пароля:
var passwordHash = require('password-hash'); var hashedPassword = passwordHash.generate('password123'); console.log(hashedPassword); // sha1$3I7HRwy7$cbfdac6008f9cab4083784cbd1874f76618d2a97
Пример использования для проверки пароля:
var passwordHash = require('./lib/password-hash'); var hashedPassword = 'sha1$3I7HRwy7$cbfdac6008f9cab4083784cbd1874f76618d2a97'; console.log(passwordHash.verify('password123', hashedPassword)); // true console.log(passwordHash.verify('Password0', hashedPassword)); // false
источник
Вы можете передать объект DocumentToObjectOptions в schema.toJSON () или schema.toObject () .
См. Определение TypeScript из @ types / mongoose
/** * The return value of this method is used in calls to JSON.stringify(doc). * This method accepts the same options as Document#toObject. To apply the * options to every document of your schema by default, set your schemas * toJSON option to the same argument. */ toJSON(options?: DocumentToObjectOptions): any; /** * Converts this document into a plain javascript object, ready for storage in MongoDB. * Buffers are converted to instances of mongodb.Binary for proper storage. */ toObject(options?: DocumentToObjectOptions): any;
DocumentToObjectOptions имеет параметр преобразования, который запускает пользовательскую функцию после преобразования документа в объект javascript. Здесь вы можете скрыть или изменить свойства в соответствии с вашими потребностями.
Итак, допустим, вы используете schema.toObject () и хотите скрыть путь к паролю из своей пользовательской схемы. Вам следует настроить общую функцию преобразования, которая будет выполняться после каждого вызова toObject ().
UserSchema.set('toObject', { transform: (doc, ret, opt) => { delete ret.password; return ret; } });
источник
Я нашел другой способ сделать это, добавив некоторые настройки в конфигурацию схемы.
const userSchema = new Schema({ name: {type: String, required: false, minlength: 5}, email: {type: String, required: true, minlength: 5}, phone: String, password: String, password_reset: String, }, { toJSON: { virtuals: true, transform: function (doc, ret) { delete ret._id; delete ret.password; delete ret.password_reset; return ret; } }, timestamps: true });
Добавив функцию преобразования к объекту toJSON с именем поля, которое нужно исключить. как в документах указано :
источник
router.get('/users',auth,(req,res)=>{ User.findById(req.user.id) //skip password .select('-password') .then(user => { res.json(user) }) })
источник
При использовании
password: { type: String, select: false }
вы должны иметь в виду, что он также исключит пароль, когда он нам понадобится для аутентификации. Так что будьте готовы справиться с этим, как хотите.источник
Это скорее следствие исходного вопроса, но это был вопрос, с которым я столкнулся, пытаясь решить свою проблему ...
А именно, как отправить пользователя обратно клиенту в обратном вызове user.save () без поля пароля.
Пример использования: пользователь приложения обновляет информацию / настройки своего профиля из клиента (пароль, контактная информация, 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); }); });
источник
const userSchema = new mongoose.Schema( { email: { type: String, required: true, }, password: { type: String, required: true, }, }, { toJSON: { transform(doc, ret) { delete ret.password; delete ret.__v; }, }, } );
источник