2012-08-23 26 views
45

Supongamos que tengo dos colecciones/esquemas. Uno es el Esquema de usuarios con campos de nombre de usuario y contraseña, luego, tengo un Esquema de blogs que tiene una referencia al Esquema de usuarios en el campo de autor. Si uso Mangosta a hacer algo como¿Cómo proteger el campo de contraseña en Mongoose/MongoDB para que no vuelva en una consulta cuando llene las colecciones?

Blogs.findOne({...}).populate("user").exec() 

voy a tener el documento Blog y el usuario poblada también, pero ¿cómo puedo evitar que la mangosta/MongoDB de devolver el campo de la contraseña? El campo de contraseña es hash pero no debe ser devuelto.

Sé que puedo omitir el campo de contraseña y devolver el resto de los campos en una consulta simple, pero ¿cómo puedo hacer eso con poblar? Además, ¿hay alguna forma elegante de hacer esto?

Además, en algunas situaciones necesito obtener el campo de contraseña, como cuando el usuario quiere iniciar sesión o cambiar la contraseña.

+0

También puede hacer .populate ('usuario': 1, 'contraseña': 0) –

Respuesta

41
.populate('user' , '-password') 

http://mongoosejs.com/docs/populate.html

JohnnyHKs respuesta utilizando las opciones de esquema es probablemente el camino a seguir aquí.

También tenga en cuenta que query.exclude() solo existe en la rama 2.x.

+0

esto también funcionará .populate ('user': 1, 'password': 0) –

3

Asumiendo que su campo de contraseña es "contraseña" que sólo puede hacer:

.exclude('password') 

No es un ejemplo más extenso here

que se centra en los comentarios, pero es el mismo principio en el juego.

Esto es lo mismo que usar una proyección en la consulta en MongoDB y pasar {"password" : 0} en el campo de proyección. Ver here

+0

Genial. Gracias. Me gusta este enfoque. –

158

Puede cambiar el comportamiento predeterminado en el nivel de definición de esquema mediante el atributo select del campo:

password: { type: String, select: false } 

Luego se puede tirar en tan necesaria en find y populate llamadas a través de la selección de campos como '+password' . Por ejemplo:

Users.findOne({_id: id}).select('+password').exec(...); 
+3

Genial. ¿Puedes dar un ejemplo sobre a quién agregarlo? Suponiendo que tengo: Users.find ({id: _id}) ¿dónde debería agregar la "+ contraseña +? –

+0

Encontré el ejemplo en el enlace que proporcionaste. Http://mongoosejs.com/docs/api.html#schematype_SchemaType-select Gracias –

+4

¿Hay alguna manera de aplicar esto al objeto pasado a save() devolución de llamada? Tal que cuando guardo un perfil de usuario la contraseña no está incluida en el parámetro de devolución de llamada. – Matt

11

Editar:

Después de probar los dos enfoques, he encontrado que el enfoque de excluir siempre no estaba trabajando para mí por alguna razón el uso de la estrategia de pasaporte local, realmente no sabemos por qué.

lo tanto, esto es lo que terminé usando:

Blogs.findOne({_id: id}) 
    .populate("user", "-password -someOtherField -AnotherField") 
    .populate("comments.items.user") 
    .exec(function(error, result) { 
     if(error) handleError(error); 
     callback(error, result); 
    }); 

No hay nada malo con el enfoque de excluir siempre, simplemente no funcionó con el pasaporte, por alguna razón, mis pruebas me dijeron que en realidad el la contraseña se excluía/incluía cuando yo quería. El único problema con el enfoque de incluir siempre es que, básicamente, necesito pasar por cada llamada que hago a la base de datos y excluir la contraseña, que es mucho trabajo.


Después de un par de grandes respuestas descubrí que hay dos maneras de hacer esto, el "siempre de inclusión y exclusión a veces" y el "siempre excluir e incluir a veces"?

Un ejemplo de los dos:

El incluir siempre pero excluye a veces ejemplo:

Users.find().select("-password") 

o

Users.find().exclude("password") 

El exlucde siempre pero incluyen a veces ejemplo:

Users.find().select("+password") 

pero se debe definir en el esquema:

password: { type: String, select: false } 
+0

Me gustaría ir por la última opción. Nunca seleccione la contraseña, excepto en el logIn/passwordUpdate funciones en las que realmente lo necesita. – rdrey

+0

Por alguna razón esa opción no funcionó con la estrategia local de Passport.js, no sé por qué. –

+0

¡Buena respuesta, gracias! No sé por qué pero cuando do '.select (" + field ")' solo trae el '__id', aunque' .select ("- field") 'excluye muy bien el campo que quiero – renatoargh

0

esto es más un corolario a la pregunta original, pero esta fue la pregunta que me encontré tratando de resolver mi problema ...

A saber, cómo enviar al usuario de vuelta al cliente en el usuario. save() devolución de llamada sin el campo de contraseña.

Caso de uso: el usuario de la aplicación actualiza su información/configuración de perfil del cliente (contraseña, información de contacto, whatevs). Desea enviar nuevamente la información de usuario actualizada al cliente en la respuesta, una vez que se haya guardado correctamente en 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); 
    }); 
}); 
0

Blogs.findOne({ _id: id }, { "password": 0 }).populate("user").exec()

3

User.find().select('-password') es la respuesta correcta. No puede agregar select: false en el esquema, ya que no funcionará, si desea iniciar sesión.

Cuestiones relacionadas