जब मैं संग्रह एकत्र करता हूं, तो यह Mongoose / MongoDB में पासवर्ड फ़ील्ड को कैसे सुरक्षित रखें, यह क्वेरी में वापस नहीं आएगा?


85

मान लीजिए मेरे पास दो संग्रह / स्कीमा हैं। एक उपयोगकर्ता नाम और पासवर्ड फ़ील्ड के साथ उपयोगकर्ता स्कीमा है, फिर, मेरे पास एक ब्लॉग स्कीमा है जिसमें लेखक क्षेत्र में उपयोगकर्ता स्कीमा का संदर्भ है। अगर मैं कुछ करने के लिए Mongoose का उपयोग करता हूं

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

मेरे पास ब्लॉग दस्तावेज़ होगा और उपयोगकर्ता बहुत अधिक आबादी वाला होगा, लेकिन मैं Mongoose / MongoDB को पासवर्ड फ़ील्ड पर वापस जाने से कैसे रोकूँ? पासवर्ड फ़ील्ड हैशेड है, लेकिन इसे वापस नहीं किया जाना चाहिए।

मुझे पता है कि मैं पासवर्ड फ़ील्ड को छोड़ सकता हूं और बाकी क्षेत्रों को एक साधारण क्वेरी में वापस कर सकता हूं, लेकिन मैं ऐसा कैसे करता हूं। इसके अलावा, क्या ऐसा करने का कोई सुरुचिपूर्ण तरीका है?

इसके अलावा, कुछ स्थितियों में मुझे पासवर्ड फ़ील्ड प्राप्त करने की आवश्यकता होती है, जैसे कि उपयोगकर्ता लॉगिन करना या पासवर्ड बदलना चाहता है।


आप भी कर सकते हैं। पोज़ करें ('उपयोगकर्ता': 1, 'पासवर्ड': 0)
सुधांशु गौर

जवाबों:


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

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

जॉनीएचकेएस स्कीमा विकल्पों का उपयोग करते हुए उत्तर देता है कि शायद यहां जाने का रास्ता है।

यह भी ध्यान दें कि query.exclude()केवल 2.x शाखा में मौजूद है।


यह भी काम करेगा। पॉपअप ('उपयोगकर्ता': 1, 'पासवर्ड': 0)
सुधांशु गौर

मुझे समझ नहीं आया कि "-" काम क्यों करता है और उत्सुक था इसलिए डॉक्स पर एक अच्छा स्पष्टीकरण पाया गया: स्ट्रिंग सिंटैक्स का उपयोग करते समय, एक पथ के साथ उपसर्ग करना - उस पथ को अलग कर देगा। जब किसी पथ में - उपसर्ग नहीं होता है, तो इसे शामिल किया जाता है। अंत में, यदि कोई पथ + के साथ उपसर्ग करता है, तो यह पथ को शामिल करने के लिए बाध्य करता है, जो स्कीमा स्तर पर बाहर किए गए रास्तों के लिए उपयोगी है। यहां पूरी बात के लिए लिंक है mongoosejs.com/docs/api.html#query_Query-select
Connor

304

आप selectक्षेत्र की विशेषता का उपयोग करके स्कीमा परिभाषा स्तर पर डिफ़ॉल्ट व्यवहार को बदल सकते हैं :

password: { type: String, select: false }

फिर आप इसे आवश्यकतानुसार चुन सकते हैं findऔर populateफ़ील्ड चयन के माध्यम से कॉल कर सकते हैं '+password'। उदाहरण के लिए:

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

3
महान। क्या आप इस पर एक उदाहरण प्रदान कर सकते हैं कि इसे किससे जोड़ना है? यह मानते हुए कि मेरे पास: Users.find ({id: _id}) है, जहां मुझे "+ पासवर्ड +?" जोड़ना चाहिए
लुइस एलैकोंडो

आपके द्वारा दिए गए लिंक पर उदाहरण मिला। mongoosejs.com/docs/api.html#schematype_SchemaType-select धन्यवाद
लुइस एलेगोंडो

9
क्या कॉलबैक () को सहेजने के लिए पास की गई वस्तु पर लागू करने का कोई तरीका है? ऐसा है कि जब मैं किसी उपयोगकर्ता प्रोफ़ाइल को सहेजता हूं तो कॉलबैक पैरामीटर में पासवर्ड शामिल नहीं होता है।
मैट

2
यह मेरी राय में अब तक का सबसे अच्छा जवाब है। इसे एक बार जोड़ें, और इसे बाहर रखा गया है। हर क्वेरी में एक चयन या बहिष्कृत विकल्प जोड़ने से बहुत बेहतर है।
एंडीएच

यह अंतिम उत्तर होना चाहिए। स्कीमा में जोड़ा गया है, और प्रश्नों के दौरान बाहर करने के लिए मत भूलना।
21

23

संपादित करें:

दोनों दृष्टिकोणों को आज़माने के बाद, मैंने पाया कि पासपोर्ट के लिए स्थानीय रणनीति का उपयोग करके किसी कारण से हमेशा अप्रोच मेरे लिए काम नहीं कर रहा था, वास्तव में पता नहीं क्यों।

तो, यह वही है जो मैंने उपयोग किया है:

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

हमेशा बहिष्कृत दृष्टिकोण के साथ कुछ भी गलत नहीं है, यह सिर्फ किसी कारण के लिए पासपोर्ट के साथ काम नहीं करता है, मेरे परीक्षणों ने मुझे बताया कि वास्तव में जब मैं चाहता / चाहती हूं तो पासवर्ड शामिल नहीं किया गया था / शामिल किया गया था। हमेशा शामिल दृष्टिकोण के साथ एकमात्र समस्या यह है कि मुझे मूल रूप से डेटाबेस पर जाने वाले हर कॉल के माध्यम से जाने और पासवर्ड को बाहर करने की आवश्यकता है जो बहुत काम है।


कुछ महान उत्तरों के बाद मुझे पता चला कि ऐसा करने के दो तरीके हैं, "हमेशा शामिल करें और कभी-कभी बाहर करें" और "हमेशा बाहर करें और कभी-कभी शामिल करें"?

दोनों का एक उदाहरण:

हमेशा शामिल करें लेकिन कभी-कभी उदाहरण को बाहर करें :

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

या

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

अतिशयोक्ति हमेशा लेकिन कभी-कभी उदाहरण में शामिल होती है :

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

लेकिन आपको स्कीमा में परिभाषित करना होगा:

password: { type: String, select: false }

मैं अंतिम विकल्प के लिए जाऊंगा। पासवर्ड का चयन कभी न करें, सिवाय लॉग इन / पासवर्ड यूडडेट कार्यों के जिन्हें आपको वास्तव में इसकी आवश्यकता है।
rdrey

किसी कारण से वह विकल्प Passport.js स्थानीय रणनीति के साथ काम नहीं करता था, पता नहीं क्यों।
लुइस एलिजाडो

अच्छा जवाब, धन्यवाद !!! पता नहीं क्यों, लेकिन जब मैं ऐसा .select("+field")करता हूं तो मैं केवल वही लाता हूं __id, भले ही .select("-field")मैं अच्छी तरह से मैदान को छोड़ देता हूं
रेनाटो गामा

क्षमा करें, यह सही काम करता है, यह ध्यान नहीं दिया गया कि select: falseअनिवार्य है
रेनैटो गामा

1
यह मेरी स्थानीय रणनीति के लिए काम कर रहा है: User.findOne ({ईमेल: उपयोगकर्ता नाम}, {पासवर्ड: 1}, async (इरेट, उपयोगकर्ता) => {...}) का इंतजार करें;
टॉमोमीहा

10

User.find().select('-password')सही उत्तर है। आप select: falseस्कीमा पर जोड़ नहीं सकते क्योंकि यह काम नहीं करेगा, यदि आप लॉगिन करना चाहते हैं।


क्या आप लॉगिन समापन बिंदु में व्यवहार को ओवरराइड नहीं कर सकते हैं? यदि हां, तो यह सबसे सुरक्षित विकल्प की तरह लगता है।
erfling

@erfling, यह नहीं होगा।
jrran90

1
यह, आप const query = model.findOne({ username }).select("+password");लॉगिन और पासवर्ड बदलने / रीसेट करने वाले मार्गों का उपयोग और उपयोग कर सकते हैं और अन्यथा यह सुनिश्चित करें कि यह कभी भी बाहर न आए। यह इस तरह से सुरक्षित है कि यह डिफ़ॉल्ट रूप से वापस नहीं आता है क्योंकि लोग गलतियों के लिए साबित होते हैं
कैकून

10

उदाहरण के लिए, स्कीमा का उपयोग करके आप इसे प्राप्त कर सकते हैं:

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

3
मैंने हर उत्तर का परीक्षण किया है, मुझे लगता है कि यदि आप एक एपीआई विकसित कर रहे हैं तो यह सबसे अच्छा विकल्प है।
asmmahmud

यह आबादी पर फ़ील्ड नहीं हटाता है।
जूलियनोटो

1
मेरे लिए सबसे अच्छा विकल्प, यह दृष्टिकोण मेरे प्रमाणीकरण विधि के साथ संघर्ष नहीं करता है
मैथियासफ़ेक

यदि आप एक एपीआई का उपयोग कर रहे हैं तो यह जाने का सबसे अच्छा तरीका है। आपको किसी क्षेत्र को हटाने के लिए भूलने की चिंता कभी नहीं करनी चाहिए :)
सैम मुनरो

4

मैं अपने 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);

3

अपना पासवर्ड फ़ील्ड मान लें "पासवर्ड" आप बस कर सकते हैं:

.exclude('password')

यहां एक अधिक व्यापक उदाहरण है

यह टिप्पणियों पर केंद्रित है, लेकिन यह खेलने में समान सिद्धांत है।

यह MongoDB में क्वेरी में एक प्रक्षेपण का उपयोग करने और {"password" : 0}प्रक्षेपण क्षेत्र में गुजरने के समान है। यहाँ देखें


महान। धन्यवाद। मुझे यह तरीका पसंद है।
लुइस एलियांडो


2

समाधान यह है कि प्लेनटेक्स्ट पासवर्ड को कभी स्टोर न करें। आपको bcrypt या पासवर्ड-हैश जैसे पैकेज का उपयोग करना चाहिए ।

पासवर्ड का उपयोग करने के लिए उदाहरण उपयोग:

 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

8
पासवर्ड के हैशड होने या न होने के बावजूद, पासवर्ड / हैश को कभी भी उपयोगकर्ता को नहीं दिखाना चाहिए। एक हमलावर हैशेड पासवर्ड की कुछ महत्वपूर्ण जानकारी प्राप्त कर सकता है (जो एल्गोरिथ्म का उपयोग किया गया था) और इसी तरह।
मार्को

2

आप schema.toJSON () या schema.toObject () के लिए DocumentToObjectOptions ऑब्जेक्ट पास कर सकते हैं ।

टाइपस्क्रिप्ट परिभाषा @ प्रकार / मानस से देखें

 /**
 * 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 में एक परिवर्तन विकल्प है जो दस्तावेज़ को जावास्क्रिप्ट ऑब्जेक्ट में कनवर्ट करने के बाद एक कस्टम फ़ंक्शन चलाता है। यहां आप अपनी आवश्यकताओं को भरने के लिए गुणों को छिपा या संशोधित कर सकते हैं।

तो, मान लें कि आप schema.toObject () का उपयोग कर रहे हैं और आप अपने उपयोगकर्ता स्कीमा से पासवर्ड पथ को छिपाना चाहते हैं। आपको एक सामान्य ट्रांसफ़ॉर्म फ़ंक्शन को कॉन्फ़िगर करना चाहिए जिसे प्रत्येक toObject () कॉल के बाद निष्पादित किया जाएगा।

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

2

स्कीमा कॉन्फ़िगरेशन में कुछ सेटिंग्स जोड़कर मुझे ऐसा करने का एक और तरीका मिला।

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 ऑब्जेक्ट में ट्रांसफ़ॉर्म फ़ंक्शन जोड़कर। के रूप में कहा गया है डॉक्स :

हमें कुछ मानदंडों के आधार पर परिणामी वस्तु का रूपांतरण करने की आवश्यकता हो सकती है, कुछ संवेदनशील जानकारी निकालने या कस्टम वस्तु वापस करने के लिए कहा जा सकता है। इस मामले में हम वैकल्पिक transformफ़ंक्शन सेट करते हैं।



1

उपयोग password: { type: String, select: false }करते समय आपको यह ध्यान रखना चाहिए कि यह प्रमाणीकरण के लिए आवश्यकता पड़ने पर पासवर्ड को भी बाहर कर देगा। इसलिए इसे तैयार करने के लिए तैयार रहें हालांकि आप चाहते हैं।


0

यह मूल प्रश्न से अधिक महत्वपूर्ण है, लेकिन यह वह प्रश्न था जो मुझे अपनी समस्या को हल करने की कोशिश में आया था ...

अर्थात्, उपयोगकर्ता को उपयोगकर्ता के पास वापस कैसे भेजें। पासवर्ड के बिना 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);
    });
});

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.