Supongamos que tengo dos colecciones/schemas. Uno de los Usuarios el Esquema con los campos de usuario y contraseña, a continuación, tengo un Blogs Esquema que tiene una referencia a los Usuarios de Esquema en el campo autor. Si yo uso la Mangosta a hacer algo como

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

Voy a tener el Blog documento y el usuario rellena demasiado, pero ¿cómo puedo evitar que la Mangosta/MongoDB desde regresando el campo de la contraseña? El campo de contraseña con hash, pero no debería ser devuelto.

Sé que puedo omitir el campo de la contraseña y devolver el resto de los campos en una consulta simple, pero ¿cómo puedo hacer que con rellenar. También, hay alguna manera elegante de hacer esto?

También, en algunas situaciones me hace falta para obtener el campo de la contraseña, como cuando el usuario quiere entrar o cambiar la contraseña.

  • también se puede hacer .rellenar(‘usuario’: 1, ‘contraseña’:0)

14 Comentarios

  1. 59
    .populate('user' , '-password')

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

    JohnnyHKs respuesta usando las opciones de Esquema es probablemente el camino a seguir aquí.

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

    • esto también funcionará .rellenar(‘usuario’: 1, ‘contraseña’:0)
  2. 248

    Usted puede cambiar el comportamiento predeterminado en el esquema de definición de nivel utilizando el seleccionar atributo del campo:

    password: { type: String, select: false }

    A continuación, usted puede tirar de él como sea necesario en find y populate llamadas a través de la selección del campo como '+password'. Por ejemplo:

    Users.findOne({_id: id}).select('+password').exec(...);
    • Gran. ¿Puede dar un ejemplo en el que se pueda añadir en la encontrar? Suponiendo que tengo: los Usuarios.find({id: _id}) donde debo de agregar el «+contraseña+?
    • Encuentra el ejemplo en el enlace proporcionado. mongoosejs.com/docs/api.html#schematype_SchemaType-select Gracias
    • Hay una forma de aplicar esto a que el objeto pasa a save() de devolución de llamada? De tal manera que cuando puedo guardar un perfil de usuario, la contraseña no está incluido en el parámetro de devolución de llamada.
    • Este es por lejos la mejor respuesta, en mi opinión. Agregar esta vez, y es excluir. Mucho mejor que la adición de un seleccionar o excluir opción para cada consulta.
    • Esta debe ser la respuesta definitiva. Añadido al esquema, y no tiene que olvidar excepto durante las consultas.
  3. 19

    Edición:

    Después de probar ambos enfoques, me encontré con que el excluir siempre enfoque no estaba funcionando para mí, por alguna razón, el uso de pasaporte-estrategia local, realmente no sé por qué.

    Así que esto es lo 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 excluir siempre enfoque, simplemente no funcionan con pasaporte por alguna razón, mis pruebas me dijo que en el hecho de que la contraseña estaba siendo excluido /incluido cuando yo quería. El único problema con el incluir siempre el enfoque es que, básicamente, necesita ir a través de cada una de las llamadas que tengo que hacer para que la base de datos y excluir la contraseña que es un montón de trabajo.


    Después de un par de grandes respuestas me enteré de que hay dos maneras de hacer esto, el «siempre incluir y excluir a veces» y «siempre a incluir y excluir a veces»?

    Un ejemplo de ambos:

    Incluir siempre, pero excluir a veces ejemplo:

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

    o

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

    La exlucde siempre, pero incluyen a veces ejemplo:

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

    pero se debe definir en el esquema:

    password: { type: String, select: false }
    • Yo iría a por la última opción. Nunca seleccione la contraseña, excepto en el inicio de sesión / passwordUpdate funciones que realmente la necesitan.
    • Por alguna razón esa opción no funciona con Passport.js estrategia local, no sé por qué.
    • Buena respuesta, gracias!!! No sé por qué, pero cuando hago .select("+field") sólo nos trae la __id, aunque .select("-field") excluye muy bien el campo que desea
    • Lo siento, funciona perfecto, no noto que select: false es obligatorio
    • Este es trabajo para mi estrategia local: esperan Usuario.findOne({ correo electrónico: nombre de usuario }, { contraseña: 1 }, async (err, el usuario) => { … });
  4. 10

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

    • No se puede reemplazar el comportamiento en el extremo de inicio de sesión? Si es así, esto parece la opción más segura.
    • no.
  5. 7

    Usted puede lograr que mediante el esquema, por ejemplo:

    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
    • He probado cada respuesta, creo que esta es la mejor opción si usted está desarrollando una api.
    • Esto no quitar campos en la población.
    • La mejor opción para mí, este enfoque haces no entre en conflicto con mi método de autenticación
  6. 3

    Suponiendo que el campo de contraseña «contraseña» usted puede hacer:

    .exclude('password')

    Existe un buen ejemplo aquí

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

    Este es el mismo como el uso de una proyección en la consulta en MongoDB y pasar {"password" : 0} en la proyección de campo. Ver aquí

    • Gran. Gracias. Me gusta este enfoque.
  7. 3

    Estoy usando para ocultar un campo de contraseña en mi REPOSO respuesta JSON

    UserSchema.methods.toJSON = function() {
     var obj = this.toObject(); //or var obj = this;
     delete obj.password;
     return obj;
    }
    
    module.exports = mongoose.model('User', UserSchema);
  8. 2

    La solución es nunca almacene contraseñas de texto plano. Usted debe utilizar un paquete como bcrypt o contraseña hash.

    Ejemplo de uso de hash de la contraseña:

     var passwordHash = require('password-hash');
    
        var hashedPassword = passwordHash.generate('password123');
    
        console.log(hashedPassword); //sha1$3I7HRwy7$cbfdac6008f9cab4083784cbd1874f76618d2a97

    Ejemplo de uso para verificar la contraseña:

    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
    • Independientemente de la contraseña de hash o no, la contraseña/el hash debería nunca se muestra al usuario. Un atacante puede obtener información importante de la contraseña con algoritmo hash (algoritmo que se utilizó) y así.
  9. 2

    Puede pasar un DocumentToObjectOptions objeto esquema.toJSON() o esquema.toObject().

    Véase la Transcripción de la definición de @/tipos de mangosta

     /**
     * 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 tiene una opción de transformar que se ejecuta una función personalizada después de convertir el documento a un objeto de javascript. Aquí usted puede ocultar o modificar las propiedades para cubrir tus necesidades.

    Así que, digamos que usted está utilizando el esquema.toObject() y desea ocultar la contraseña camino de su esquema de Usuario. Usted debe configurar un general de transformación de la función que se ejecuta después de cada toObject() la llamada.

    UserSchema.set('toObject', {
      transform: (doc, ret, opt) => {
       delete ret.password;
       return ret;
      }
    });
  10. 1

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

    • Esta es la correcta respuesta clara.
  11. 1

    Mientras que el uso de password: { type: String, select: false } usted debe tener en cuenta que también excluirá la contraseña cuando la necesitamos para la autenticación. Así que esté preparado para manejarlo sin embargo que usted desea.

  12. 0

    Esto es más que un corolario a la pregunta original, pero esta era la pregunta que me encontré tratando de resolver mi problema…

    Es decir, cómo se va a enviar al usuario de vuelta al cliente en el usuario.save() de devolución de llamada sin el campo de la contraseña.

    Caso de uso: el usuario de la aplicación de las actualizaciones de la información de su perfil/configuración del cliente (contraseña, información de contacto, whatevs). Desea enviar la actualización de la información de usuario de vuelta al cliente en la respuesta, una vez que se ha guardado con éxito a 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);
        });
    });
  13. 0

    He encontrado otra manera de hacerlo, mediante la adición de algunos ajustes a la configuración del esquema.

    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 });

    Mediante la adición de función de transformación para toJSON objeto con el nombre de campo para excluir. como En docs declaró:

    Podemos necesitar realizar una transformación del objeto resultante basado en
    en algún criterio, por ejemplo, para quitar algo de información confidencial o la devolución de una
    objeto personalizado. En este caso hemos creado el opcional transform función.

  14. 0
    router.get('/users',auth,(req,res)=>{
       User.findById(req.user.id)
        //skip password
        .select('-password')
        .then(user => {
            res.json(user)
        })
    })

Dejar respuesta

Please enter your comment!
Please enter your name here