it-swarm.com.de

Wie kann ich das Kennwortfeld in Mongoose/MongoDB schützen, damit es in einer Abfrage nicht angezeigt wird, wenn ich Sammlungen auffülle?

Angenommen, ich habe zwei Sammlungen/Schemas. Eines ist das Benutzerschema mit Benutzernamen und Kennwort, und dann habe ich ein Blogs-Schema, das einen Verweis auf das Benutzerschema im Autorenfeld hat. Wenn ich Mongoose benutze, um so etwas zu tun

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

Ich habe das Blog-Dokument und den Benutzer ebenfalls ausgefüllt. Wie kann ich jedoch verhindern, dass Mongoose/MongoDB das Kennwortfeld zurückgibt? Das Passwortfeld ist gehasht, sollte aber nicht zurückgegeben werden.

Ich weiß, ich kann das Kennwortfeld weglassen und den Rest der Felder in einer einfachen Abfrage zurückgeben, aber wie mache ich das mit Auffüllen? Gibt es auch eine elegante Möglichkeit, dies zu tun?

In einigen Situationen muss ich auch das Kennwortfeld abrufen, z. B. wenn der Benutzer sich anmelden oder das Kennwort ändern möchte.

60
Luis Elizondo
.populate('user' , '-password')

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

JohnnyHKs Antwort mit Schema-Optionen ist wahrscheinlich der Weg, um hier zu gehen.

Beachten Sie auch, dass query.exclude() nur im 2.x-Zweig vorhanden ist.

49
aaronheckmann

Sie können das Standardverhalten auf der Ebene der Schemadefinition mithilfe des Attributs select des Felds ändern:

password: { type: String, select: false }

Sie können es dann in find- und populate-Aufrufen über Feldauswahl als '+password' nach Bedarf abrufen. Zum Beispiel:

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

Bearbeiten: 

Nachdem ich beide Ansätze ausprobiert hatte, stellte ich fest, dass der Ansatz "ausschließen" für mich aus irgendeinem Grund nicht mit der lokalen Strategie des Passes funktionierte. Ich weiß nicht, warum.

Also habe ich am Ende verwendet:

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

Es gibt nichts Falsches an der Methode Exclude-Always. Aus irgendeinem Grund funktionierte es einfach nicht mit Pass. In meinen Tests wurde mir mitgeteilt, dass das Passwort tatsächlich ausgeschlossen/ausgeschlossen wurde, wenn ich wollte. Das einzige Problem bei der Methode "include always" ist, dass ich grundsätzlich jeden Aufruf der Datenbank durchgehen und das Kennwort ausschließen muss, was sehr viel Arbeit bedeutet.


Nach ein paar großartigen Antworten habe ich herausgefunden, dass es zwei Möglichkeiten gibt, dies zu tun: "Manchmal immer einschließen und ausschließen" und "Immer ausschließen und manchmal einschließen"?

Ein Beispiel für beide:

Das Include immer aber manchmal ausschließen Beispiel:

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

oder

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

Das Exlucde immer aber manchmal einschließen Beispiel:

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

aber Sie müssen im Schema definieren:

password: { type: String, select: false }
14
Luis Elizondo

User.find().select('-password') ist die richtige Antwort. Sie können select: false nicht zum Schema hinzufügen, da es nicht funktioniert, wenn Sie sich anmelden möchten.

7
Ylli Gashi

Angenommen, Ihr Passwortfeld ist "Passwort", können Sie einfach Folgendes tun:

.exclude('password')

Es gibt ein ausführlicheres Beispiel hier

Das ist auf Kommentare fokussiert, aber es ist das gleiche Prinzip im Spiel.

Dies entspricht der Verwendung einer Projektion in der Abfrage in MongoDB und der Übergabe von {"password" : 0} im Projektionsfeld. Siehe hier

4
Adam Comerford

Die Lösung besteht darin, niemals Klartextkennwörter zu speichern. Sie sollten ein Paket wie [bcrypt]1 oder [password-hash]2 verwenden.

Beispiel zur Verwendung des Passworts:

 var passwordHash = require('password-hash');

    var hashedPassword = passwordHash.generate('password123');

    console.log(hashedPassword); // sha1$3I7HRwy7$cbfdac6008f9cab4083784cbd1874f76618d2a97

Beispiel zur Verwendung des Kennworts:

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
2
Cameron Hudson

Sie können dies mit dem Schema erreichen, zum Beispiel:

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
2
Ikbel

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

1
Ricky

Ich verwende das Feld zum Ausblenden des Kennworts in meiner REST JSON-Antwort

UserSchema.methods.toJSON = function() {
 var obj = this.toObject();
 delete obj.password;
 return obj;
}

module.exports = mongoose.model('User', UserSchema);
1
Gere

Bei der Verwendung von password: { type: String, select: false } sollten Sie berücksichtigen, dass bei der Authentifizierung auch ein Kennwort ausgeschlossen wird. Seien Sie also bereit, damit umzugehen, wie Sie möchten.

0
Anand Kapdi

Sie können einDocumentToObjectOptionsObjekt anschema.toJSON ()oderschema.toObject ()übergeben. _ .

Siehe TypeScript-Definition von @ 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;

DocumentToObjectOptionshat eine Transformationsoption, die eine benutzerdefinierte Funktion ausführt, nachdem das Dokument in ein Javascript-Objekt konvertiert wurde. Hier können Sie Eigenschaften verbergen oder ändern, um Ihre Anforderungen zu erfüllen.

Angenommen, Sie verwenden schema.toObject () und möchten den Kennwortpfad in Ihrem Benutzerschema ausblenden. Sie sollten eine allgemeine Transformationsfunktion konfigurieren, die nach jedem Aufruf von toObject () ausgeführt wird.

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

Dies ist eher eine Folge der ursprünglichen Frage, aber auf diese Frage bin ich gestoßen, als ich versuchte, mein Problem zu lösen ... 

Nämlich, wie man den Benutzer im user.save () - Rückruf ohne das Kennwortfeld an den Client zurücksendet.

Anwendungsfall: Der Anwendungsbenutzer aktualisiert seine Profilinformationen/-einstellungen vom Client (Kennwort, Kontaktinformationen, whatevs). Sie möchten die aktualisierten Benutzerinformationen in der Antwort zurück an den Client senden, nachdem sie erfolgreich in MongoDB gespeichert wurden.

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
Bennett Adams