Angenommen, ich habe zwei Sammlungen / Schemata. Eines ist das Benutzerschema mit Benutzernamen- und Kennwortfeldern. Dann habe ich ein Blogs-Schema, das einen Verweis auf das Benutzerschema im Autorenfeld enthält. Wenn ich Mungo benutze, um so etwas zu tun
Blogs.findOne({...}).populate("user").exec()
Ich werde das Blog-Dokument und den Benutzer ebenfalls ausfüllen lassen, aber wie kann ich verhindern, dass Mongoose / MongoDB das Kennwortfeld zurückgibt? Das Passwortfeld ist gehasht, sollte aber nicht zurückgegeben werden.
Ich weiß, dass ich das Kennwortfeld weglassen und den Rest der Felder in einer einfachen Abfrage zurückgeben kann, aber wie mache ich das mit populate. 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.
Antworten:
.populate('user' , '-password')
http://mongoosejs.com/docs/populate.html
JohnnyHKs Antwort mit Schema-Optionen ist wahrscheinlich der richtige Weg.
Beachten Sie auch, dass
query.exclude()
nur in der 2.x-Verzweigung vorhanden ist.quelle
Sie können das Standardverhalten auf der Ebene der Schemadefinition mithilfe des
select
Attributs des Felds ändern :password: { type: String, select: false }
Dann können Sie es nach Bedarf einziehen
find
undpopulate
über die Feldauswahl als anrufen'+password'
. Zum Beispiel:Users.findOne({_id: id}).select('+password').exec(...);
quelle
Bearbeiten:
Nachdem ich beide Ansätze ausprobiert hatte, stellte ich fest, dass der Ansatz "Ausschluss immer" bei mir aus irgendeinem Grund mit einer passportlokalen Strategie nicht funktionierte. Ich weiß nicht wirklich warum.
Das habe ich also benutzt:
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 ist nichts Falsches daran, immer auszuschließen, es hat aus irgendeinem Grund einfach nicht mit dem Reisepass funktioniert. Meine Tests haben mir gezeigt, dass das Passwort tatsächlich ausgeschlossen / eingeschlossen wurde, als ich wollte. Das einzige Problem mit dem Ansatz "Immer einschließen" ist, dass ich grundsätzlich jeden Aufruf der Datenbank durchlaufen und das Kennwort ausschließen muss, was viel Arbeit bedeutet.
Nach ein paar großartigen Antworten fand ich heraus, dass es zwei Möglichkeiten gibt, dies zu tun: "Immer einschließen und manchmal ausschließen" und "Immer ausschließen und manchmal einschließen"?
Ein Beispiel für beides:
Das schließt immer aber manchmal ein Beispiel ein:
Users.find().select("-password")
oder
Users.find().exclude("password")
Die exlucde immer aber manchmal Beispiel enthalten:
Users.find().select("+password")
Sie müssen jedoch im Schema Folgendes definieren:
password: { type: String, select: false }
quelle
.select("+field")
, bringt es nur das__id
, obwohl es.select("-field")
das Feld, das ich will, gut ausschließtselect: false
obligatorisch istUser.find().select('-password')
ist die richtige Antwort. Sie könnenselect: false
das Schema nicht hinzufügen, da es nicht funktioniert, wenn Sie sich anmelden möchten.quelle
const query = model.findOne({ username }).select("+password");
bei Anmelde- und Kennwortänderungs- / Rücksetzrouten verwenden und ansonsten sicherstellen, dass es niemals herauskommt. Dies ist bei weitem sicherer, wenn es nicht standardmäßig zurückgegeben wird, da Menschen nachweislich Fehler imoSie 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
quelle
Ich verwende zum Ausblenden des Kennwortfelds in meiner REST-JSON-Antwort
UserSchema.methods.toJSON = function() { var obj = this.toObject(); //or var obj = this; delete obj.password; return obj; } module.exports = mongoose.model('User', UserSchema);
quelle
Angenommen, Ihr Passwortfeld ist "Passwort", können Sie einfach Folgendes tun:
.exclude('password')
Es gibt ein ausführlicheres Beispiel hier
Das konzentriert sich auf Kommentare, aber es ist das gleiche Prinzip im Spiel.
Dies entspricht der Verwendung einer Projektion in der Abfrage in MongoDB und der Übergabe
{"password" : 0}
im Projektionsfeld. Siehe hierquelle
Blogs.findOne({ _id: id }, { "password": 0 }).populate("user").exec()
quelle
Die Lösung besteht darin, niemals Klartextkennwörter zu speichern. Sie sollten ein Paket wie bcrypt oder password-hash verwenden .
Beispiel für die Verwendung des Passworts:
var passwordHash = require('password-hash'); var hashedPassword = passwordHash.generate('password123'); console.log(hashedPassword); // sha1$3I7HRwy7$cbfdac6008f9cab4083784cbd1874f76618d2a97
Beispiel für die Verwendung zur Überprüfung 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
quelle
Sie können ein DocumentToObjectOptions- Objekt an schema.toJSON () oder schema.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;
DocumentToObjectOptions verfügt über eine Transformationsoption, die eine benutzerdefinierte Funktion ausführt, nachdem das Dokument in ein Javascript-Objekt konvertiert wurde. Hier können Sie Eigenschaften ausblenden oder ändern, um Ihre Anforderungen zu erfüllen.
Angenommen, Sie verwenden schema.toObject () und möchten den Kennwortpfad aus 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; } });
quelle
Ich habe einen anderen Weg gefunden, dies zu tun, indem ich der Schemakonfiguration einige Einstellungen hinzugefügt habe.
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 });
Durch Hinzufügen einer Transformationsfunktion zum JSON-Objekt mit dem auszuschließenden Feldnamen. wie in den Dokumenten angegeben :
quelle
router.get('/users',auth,(req,res)=>{ User.findById(req.user.id) //skip password .select('-password') .then(user => { res.json(user) }) })
quelle
Beachten
password: { type: String, select: false }
Sie bei der Verwendung, dass das Kennwort auch dann ausgeschlossen wird, wenn wir es zur Authentifizierung benötigen. Seien Sie also bereit, damit umzugehen, wie Sie wollen.quelle
Dies ist eher eine Folge der ursprünglichen Frage, aber dies war die Frage, auf die ich stieß, als ich versuchte, mein Problem zu lösen ...
Das heißt, wie der Benutzer im Rückruf user.save () ohne das Kennwortfeld an den Client zurückgesendet wird.
Anwendungsfall: Der Anwendungsbenutzer aktualisiert seine Profilinformationen / -einstellungen vom Client (Kennwort, Kontaktinformationen, Whatevs). Sie möchten die aktualisierten Benutzerinformationen in der Antwort an den Client zurücksenden, sobald 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); }); });
quelle
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; }, }, } );
quelle