2017-05-11 16 views
5

के साथ सर्वोत्तम प्रथाओं का प्रसंस्करण प्रपत्र मैं एक ऐसी वेबसाइट लिख रहा हूं जो एक उपयोगकर्ता प्रबंधन प्रणाली लागू करता है और मुझे आश्चर्य है कि प्रपत्र प्रसंस्करण के संबंध में सर्वोत्तम प्रथाओं पर मुझे क्या विचार करना है।एक्सप्रेस

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

केस का उपयोग करें: कोई भी अपनी प्रोफ़ाइल के जन्मदिन को अपडेट करने जा रहा है। अभी मैं उसी पृष्ठ पर फ़ॉर्म को संसाधित करने के लिए एक ही यूआरएल के लिए एक POST अनुरोध कर रहा हूं और POST अनुरोध उसी यूआरएल पर 302 रीडायरेक्ट के साथ जवाब देगा।

प्रपत्र प्रसंस्करण के बारे में सामान्य प्रश्न:

  1. मैं एक पोस्ट अनुरोध + 302 करना चाहिए प्रपत्र प्रसंस्करण या बल्कि एक AJAX अनुरोध की तरह कुछ और के लिए पुनर्निर्देशित?
  2. मुझे अमान्य FORM अनुरोधों को कैसे प्रबंधित करना चाहिए (उदाहरण के लिए अमान्य लॉगिन, या ईमेल पता पहले ही साइनअप के दौरान उपयोग में है)?
  3. प्रपत्र प्रसंस्करण के बारे में

एक्सप्रेस विशिष्ट प्रश्न:

  1. मेरी DB में कुछ भी डालने से पहले मैं स्वच्छ और सर्वर साइड पर सभी फ़ॉर्म फ़ील्ड को मान्य करने की जरूरत है मुझे लगता है । आप वह कैसे करेंगें?

  2. मैंने सीएसआरएफ के बारे में कुछ चीजें पढ़ी लेकिन मैंने कभी सीएसआरएफ सुरक्षा लागू नहीं की है। मुझे यह देखने में खुशी होगी कि कोड स्निपेट में भी

  3. क्या मुझे एक्सप्रेस के साथ फ़ॉर्म प्रोसेस करते समय किसी अन्य संभावित भेद्यता का ख्याल रखने की आवश्यकता है?

उदाहरण HTML/पग:

form#profile(method='POST', action='/settings/profile') 
    input#profile-real-name.validate(type='text', name='profileRealName', value=profile.name) 
    label(for='profile-real-name') Name 

    textarea#profile-bio.materialize-textarea(placeholder='Tell a little about yourself', name='profileBio') 
     | #{profile.bio} 
    label(for='profile-bio') About 

    input#profile-url.validate(type='url', name='profileUrl', value=profile.bio) 
    label(for='profile-url') URL 

    input#profile-location.validate(type='text', name='profileLocation', value=profile.location) 
    label(for='profile-location') Location 

    .form-action-buttons.right-align 
     a.btn.grey(href='' onclick='resetForm()') Reset 
     button.btn.waves-effect.waves-light(type='submit') 

उदाहरण मार्ग हैंडलर:

router.get('/settings/profile', isLoggedIn, profile) 
router.post('/settings/profile', isLoggedIn, updateProfile) 

function profile(req, res) { 
    res.render('user/profile', { title: 'Profile', profile: req.user.profile }) 
} 

function updateProfile(req, res) { 
    var userId = req.user._id 
    var form = req.body 
    var profile = { 
     name: form.profileRealName, 
     bio: form.profileBio, 
     url: form.profileUrl, 
     location: form.profileLocation 
    } 

    // Insert into DB 
} 

नोट: एक संपूर्ण कोड स्निपेट जो सबसे अच्छा प्रसंस्करण सभी प्रपत्र का ख्याल रखता है दिए गए उदाहरण के लिए अनुकूलित प्रथाओं की अत्यधिक सराहना की जाती है। मैं सार्वजनिक रूप से उपलब्ध एक्सप्रेस मिडलवेयर का उपयोग करने के साथ ठीक हूं।

उत्तर

2

मैं एक पोस्ट अनुरोध + 302 प्रपत्र प्रसंस्करण के लिए पुन: निर्देशन या नहीं बल्कि कुछ और एक AJAX अनुरोध पसंद करते हैं चाहिए?

नहीं, एक अच्छा उपयोगकर्ता अनुभव 2004 के बाद से या तो (मूल रूप से के बाद से जीमेल शुरू की) और नहीं वेब 1.0 पूरे पृष्ठ लोड फ़ॉर्म पोस्ट AJAX के माध्यम से फ़ॉर्म जमा कर दिया गया है के लिए सबसे अच्छा अभ्यास। विशेष रूप से, AJAX के माध्यम से त्रुटि प्रबंधन आपके उपयोगकर्ता को एक मृत अंत ब्राउज़र त्रुटि पृष्ठ पर छोड़ने की संभावना कम है और उसके बाद बैक बटन के साथ समस्याएं दबाएं। इस मामले में AJAX को एक HTTP पैच अनुरोध सबसे अधिक अर्थात् सही होने के लिए भेजना चाहिए लेकिन पोस्ट या PUT भी काम पूरा हो जाएगा।

मैं कैसे संभाल चाहिए अवैध फार्म अनुरोध (उदाहरण के अवैध प्रवेश, या ईमेल पते के लिए साइन अप के दौरान पहले से प्रयोग में है)?

अमान्य उपयोगकर्ता इनपुट एक JSON प्रतिक्रिया शरीर में विशिष्ट त्रुटि (रों) के बारे में विवरण (प्रारूप आवेदन के साथ बदलती है, लेकिन साथ एक HTTP 400 Bad Request स्थिति कोड के जवाब में परिणाम चाहिए, या तो एक सामान्य संदेश या क्षेत्र के द्वारा -फील्ड त्रुटियां आम विषयों हैं)

ईमेल पहले से उपयोग में आने के लिए मैं HTTP 409 Conflict स्थिति कोड का उपयोग सामान्य बुरे अनुरोध पेलोड के अधिक विशेष स्वाद के रूप में करता हूं।

मैं अपने DB में कुछ भी डालने से पहले मैं स्वच्छ और सर्वर साइड पर सभी फ़ॉर्म फ़ील्ड को मान्य करने की जरूरत है मान। आप वह कैसे करेंगें?

बिल्कुल। कई उपकरण हैं। मैं आम तौर पर JSON Schema में एक वैध अनुरोध के लिए एक स्कीमा परिभाषित करता हूं और is-my-json-valid या ajv जैसे मान्य करने के लिए एनपीएम से लाइब्रेरी का उपयोग करता हूं। विशेष रूप से, मैं जितना संभव हो उतना सख्त होने की अनुशंसा करता हूं: यदि आपको जरूरी है, तो गलत प्रकारों को अस्वीकार करें, या कॉरर्स प्रकारों को अस्वीकार करें, अप्रत्याशित गुणों को हटाएं, छोटे लेकिन उचित स्ट्रिंग लंबाई सीमाओं और तारों के लिए सख्त नियमित अभिव्यक्ति पैटर्न का उपयोग करें, और निश्चित रूप से सुनिश्चित करें कि आपका डीबी पुस्तकालय संपत्ति इंजेक्शन हमलों से बचाता है।

मैं CSRF के बारे में कुछ बातें पढ़ने के लिए लेकिन मैं एक CSRF संरक्षण से लागू नहीं किया है।

OWSAP Node Goat Project CSRF Exercise लिए एक अच्छी जगह है, एक कमजोर अनुप्रयोग के साथ शुरू करने के लिए समझने के लिए और भेद्यता का उपयोग करें, तो ठीक (लागू express.csrf() मिडलवेयर का एक सीधा एकीकरण के साथ इस मामले में है।

मैं जब एक्सप्रेस के साथ रूपों प्रसंस्करण किसी अन्य संभव कमजोरियों की देखभाल की जरूरत है?

हाँ आम तौर पर एप्लिकेशन डेवलपर्स को समझना और सक्रिय रूप से कोड को सुरक्षित रूप से समझना चाहिए। इस पर बहुत सारी सामग्री है लेकिन जब उपयोगकर्ता इनपुट डेटाबेस क्वेरी, सबप्रोसेस स्पॉन्गिंग, या HTML पर वापस लिखा जा रहा है, तो विशेष देखभाल की जानी चाहिए। सॉलिड क्वेरी लाइब्रेरीज़ और टेम्पलेट इंजन यहां अधिकांश कामों को संभाल लेंगे, आपको केवल मैकेनिक्स और संभावित स्थानों से अवगत होना चाहिए, दुर्भावनापूर्ण उपयोगकर्ता इनपुट में छेड़छाड़ की जा सकती है (जैसे छवि फ़ाइल नाम, इत्यादि)।

+0

समय लेने के लिए धन्यवाद, क्या आप एक असली दुनिया कोड उदाहरण दिखाते हैं जो दर्शाता है कि आप कैसे एक फॉर्म को स्वच्छ और वैध कर रहे हैं? इससे मुझे आपके दृष्टिकोण को समझने में मदद मिलेगी। यदि आप सोचते हैं तो मैं मोंगोज़ का उपयोग कर रहा हूं। – kentor

+0

मैं मोंगोज़ को बहुत पसंद करता हूं, इसलिए माफ करना नहीं। –

1

मैं निश्चित रूप से कोई एक्सप्रेस विशेषज्ञ हूँ, लेकिन मुझे लगता है कि मैं जवाब कर सकते हैं कम से कम # 1:

आप का पालन करना चाहिए पोस्ट/रीडायरेक्ट/आदेश डुप्लिकेट फ़ॉर्म सबमिशन को रोकने के लिए वेब विकास पैटर्न प्राप्त करें। मैंने सुना है कि 303-रीडायरेक्ट फॉर्म सबमिशन को पुनर्निर्देशित करने के लिए उचित http स्थिति कोड है।

मैं पोस्ट रूट का उपयोग कर प्रोसेस प्रोसेस करता हूं और एक बार जब मैं कर रहा हूं तो मैं 302-रीडायरेक्ट ट्रिगर करता हूं।

# 3 के रूप में मैं एक्सप्रेस-सत्यापनकर्ता की तलाश करने की अनुशंसा करता हूं, जो यहां अच्छी तरह से पेश है: https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/forms।यह एक मध्यस्थ जो आप को सत्यापित करने और इस तरह स्वच्छ करने की अनुमति देता है:

req.checkBody('name', 'Invalid name').isAlpha(); 
req.checkBody('age', 'Invalid age').notEmpty().isInt(); 
req.sanitizeBody('name').escape(); 

मैं इसलिए जवाब भले ही यह एक पूरा जवाब नहीं है टिप्पणी करने के लिए सक्षम नहीं था। बस सोचा कि यह आपकी मदद कर सकता है।

1

यदि उपयोगकर्ता अनुभव ऐसा कुछ है जिसके बारे में आप सोच रहे हैं, तो पृष्ठ पुनर्निर्देशन एक मजबूत संख्या है। अपनी वेबसाइट पर आने वाले लोगों के लिए एक आसान प्रवाह प्रदान करना बूंदों को रोकने के लिए महत्वपूर्ण है, और चूंकि फॉर्म भरने के लिए पहले से ही इतनी खुशी नहीं है, उनके उपयोग को आसान बनाना प्राथमिक है। आप अपने पृष्ठ को फिर से लोड नहीं करना चाहते हैं जो शायद एक त्रुटि संदेश प्रदर्शित करने के लिए लोड करने में कुछ समय लगेगा। एक बार फॉर्म वैध होने के बाद और आपने उपयोगकर्ता कुकी बनाई है, फिर भी एक पुनर्निर्देशन ठीक है, भले ही आप इसे रोकने के लिए क्लाइंट ऐप पर चीजें कर सकें, लेकिन यह आउट-ऑफ-स्कोप है।

जैसा कि लीवेंट ने कहा है, आपको express-validator चेकआउट करना चाहिए, जो इस तरह के उद्देश्य के लिए अधिक स्थापित समाधान है।

req.check('profileRealName', 'Bad name provided').notEmpty().isAlpha() 
req.check('profileLocation', 'Invalid location').optional().isAlpha(); 

req.getValidationResult().then(function (result) { 
    if (result.isEmpty()) { return null } 
    var errors = result.array() 
    // [ 
    // { param: "profileRealName", msg: "Bad name provided", value: ".." }, 
    // { param: "profileLocation", msg: "Invalid location", value: ".." } 
    // ] 
    res.status(400).send(errors) 
}) 
.then(function() { 
    // everything is fine! insert into the DB and respond.. 
}) 

ऐसा लगता है कि, मुझे लगता है कि आप MongoDB का उपयोग कर रहे हैं। यह देखते हुए, मैं एक ओडीएम का उपयोग करने की सिफारिश करता हूं, जैसे Mongoose। यह आपको अपने स्कीमा के लिए मॉडल को परिभाषित करने और सीधे इस पर प्रतिबंध लगाने की अनुमति देगा, जिससे मॉडल आपके लिए इस तरह के अनावश्यक सत्यापन को संभाल सके।

उदाहरण के लिए, अपने उपयोगकर्ता के लिए एक मॉडल होना

var User = new Schema({ 
    name: { type: String, required: [true, 'Name required'] }, 
    bio: { type: String, match: /[a-z]/ }, 
    age: { type: Number, min: 18 }, // I don't know the kind of site you run ;) 
}) 

अपने मार्ग पर इस स्कीमा का उपयोग करते हुए की तरह

var user = new User({ 
    name: form.profileRealName, 
    bio: form.profileBio, 
    url: form.profileUrl, 
    location: form.profileLocation 
}) 

user.save(function (err) { 
    // and you could grab the error here if it exists, and react accordingly 
}); 

देख रहा होगा सकता है आप देख सकते हैं कि यह एक बहुत अच्छा एपीआई, प्रदान करता है जो यदि आप और जानना चाहते हैं तो आपको their docs में पढ़ना चाहिए।

सीआरएसएफ के बारे में, आपको csurf इंस्टॉल करना चाहिए, जिसमें उनके अच्छे रीमेम पर बहुत अच्छे निर्देश और उदाहरण उपयोग हैं।

उसके बाद आप जाने के लिए बहुत अच्छे हैं, यह सुनिश्चित करने के अलावा कि आप अपनी महत्वपूर्ण निर्भरताओं के साथ अद्यतित रहें, 0-दिन होने पर, उदाहरण के लिए the one हुआ 2015 में जेडब्ल्यूटी के साथ, लेकिन यह अभी भी दुर्लभ है।