2009-10-25 15 views
110

मैं this Railscast episode पर देख रहा हूँ और सोच क्यों escape_javascript करने के लिए कॉल यहाँ की जरूरत है:आंशिक रूप से प्रस्तुत करने से पहले escape_javascript क्यों?

$("#reviews").append("<%= escape_javascript(render(:partial => @review)) %>"); 

क्या escape_javascript के लिए प्रयोग किया जाता है?

the Rails docs के अनुसार:

escape_javascript (जावास्क्रिप्ट)

भागने वाहक रिटर्न और एकल और जावास्क्रिप्ट क्षेत्रों के लिए दोहरे उद्धरण चिह्नों।

लेकिन इसका मतलब मेरे लिए बहुत मायने नहीं रखता है।

+19

FYI का जावास्क्रिप्ट निष्पादित नहीं करेगा, यहां स्वीकृत उत्तर सही उत्तर नहीं है। किकिटो – Steve

उत्तर

1

क्योंकि आप नहीं चाहते हैं कि उपयोगकर्ता जावास्क्रिप्ट पोस्ट करते हैं कि ब्राउज़र वास्तव में निष्पादित करता है?

+4

है लेकिन जब आप जावास्क्रिप्ट कोड पास करना और प्रस्तुत करना चाहते हैं तो कैसे? – berto77

+0

हाँ, वास्तव में यह एक स्वरूपण विधि से अधिक है।यह उपयोगकर्ताओं को अपनी जावास्क्रिप्ट निष्पादित करने से नहीं रोकता है। कुछ भी इसे रोक नहीं सकता है। – Deviljho

+2

यह सहायक नहीं है। इसके बजाय [kikito का जवाब] (http://stackoverflow.com/a/1623813/703233) देखें। – nitsas

8

उपयोगकर्ता दुर्भावनापूर्ण कोड (दुर्भावनापूर्ण उपयोगकर्ता) पोस्ट कर सकते हैं कि अगर छोड़ा गया तो संभावित रूप से निष्पादित हो जाएगा, जिससे उपयोगकर्ता आपके आवेदन को नियंत्रित कर सकते हैं।

इस प्रयास करें:

<% variable = '"); alert("hi there' %> 
$("#reviews").append("<%= variable %>"); 

वास्तव में रेल की वाक्य रचना से परिचित नहीं है, लेकिन अगर आप variable बच नहीं है तो एक बॉक्स दिखाई देगा, और मुझे नहीं लगता है कि इरादा व्यवहार है।

327

यदि आप कोड को दो भागों में विभाजित करते हैं तो यह समझना आसान है।

पहला भाग $("#reviews").append("<%= ... %>"); एआरबी के साथ जावास्क्रिप्ट है। इसका मतलब है कि <%= ... %> इसके बदले में रूबी कोड जो भी लौटाएगा, उसे प्रतिस्थापित कर दिया जाएगा। उस प्रतिस्थापन का परिणाम वैध जावास्क्रिप्ट होना चाहिए, अन्यथा जब यह क्लाइंट इसे संसाधित करने का प्रयास करता है तो यह एक त्रुटि फेंक देगा। तो यह पहली बात है: आपको मान्य जावास्क्रिप्ट की आवश्यकता है।

ध्यान में रखना एक और बात यह है कि जो भी रूबी उत्पन्न करता है उसे डबल कोट्स के साथ जावास्क्रिप्ट स्ट्रिंग के अंदर निहित होना चाहिए - <%= ... %> के आसपास डबल कोट्स देखें। इसका मतलब है कि उत्पन्न जावास्क्रिप्ट इस तरह दिखेगा:

$("#reviews").append("..."); 

अब <%= ... %> अंदर गहरे लाल रंग का हिस्सा जांच करते हैं। render(:partial => @review) क्या करता है? यह आंशिक प्रतिपादन कर रहा है - जिसका अर्थ है कि यह किसी भी प्रकार का कोड - एचटीएमएल, सीएसएस ... या इससे भी अधिक जावास्क्रिप्ट प्रस्तुत कर सकता है!

तो, क्या होता है यदि हमारे आंशिक में कुछ सरल HTML शामिल है, तो इस तरह?

<a href="/mycontroller/myaction">Action!</a> 

याद रखें कि आपका जावास्क्रिप्ट एक पैरामीटर के रूप में डबल-उद्धृत स्ट्रिंग ले रहा था? अगर हम उस आंशिक कोड के साथ <%= ... %> को प्रतिस्थापित करते हैं, तो हमें एक समस्या है - href= के तुरंत बाद एक डबल कोट है!जावास्क्रिप्ट मान्य नहीं होगा:

// Without escaping, you get a broken javascript string at href 
$("#reviews").append("<a href="/mycontroller/myaction">Action!</a>"); 
इस के लिए

आदेश में ऐसा नहीं है, तो आप भागने करने के लिए इन विशेष वर्ण चाहते हैं तो अपने स्ट्रिंग में कटौती नहीं कर रहा है - अगर आप कुछ है कि इस के बजाय उत्पन्न की जरूरत है:

<a href=\"/mycontroller/myaction\">Action!</a> 

यह escape_javascript करता है। यह सुनिश्चित करता है कि लौटाई गई स्ट्रिंग जावास्क्रिप्ट को "तोड़" नहीं देगी। यदि आप इसका उपयोग करते हैं, तो आपको वांछित आउटपुट मिलेगा:

$("#reviews").append("<a href=\"/mycontroller/myaction\">Action!</a>") 

सम्मान!

+4

वास्तव में, बहुत अच्छी व्याख्या आपको धन्यवाद। मुझे लगता है कि 'escape_javascript' का उपयोग करना भ्रामक है क्योंकि हम वास्तव में वास्तविक जावास्क्रिप्ट से बचने के लिए इसका उपयोग नहीं कर रहे हैं। आप आंशिक रूप से एक स्क्रिप्ट टैग डाल सकते हैं और अपनी इच्छित जावास्क्रिप्ट निष्पादित कर सकते हैं। – Steve

+12

@ स्टेव सहमत हुए, एक बेहतर नाम 'escape_for_javascript' होगा, क्योंकि अक्सर आप अन्य कोड से बच रहे हैं (उदाहरण के लिए एचटीएमएल) ताकि यह जावास्क्रिप्ट को तोड़ न सके। – kikito

+13

'escape_javascript()' अब एक छोटी विधि है: सरल 'j() '(कम से कम रेल 4 में)। – mjnissim

7

यदि आप स्रोत here पर स्रोत देखते हैं, तो यह बहुत स्पष्ट होगा।

इस समारोह के बाद दो बातें सिद्ध:

  1. यह लोगों JS_ESCAPE_MAP

    इसका उद्देश्य यह सुनिश्चित करना है में परिभाषित के साथ इनपुट स्ट्रिंग में वर्णों विकल्प है कि जावास्क्रिप्ट कोड बाहरी स्ट्रिंग के साथ हस्तक्षेप किए बिना सही ढंग से क्रमबद्ध किया गया है जिसमें इसे एम्बेड किया जा रहा है। उदाहरण के लिए यदि आपके पास डबल कोट्स में जावास्क्रिप्ट स्ट्रिंग है तो स्ट्रिंग अक्षर के लिए सभी उद्धरण ब्रेकिंग से कोड से बचने के लिए सिंगल कोट्स में होना चाहिए।

  2. फ़ंक्शन यह भी जांचता है कि परिणामस्वरूप स्ट्रिंग HTML सुरक्षित है या नहीं। यदि ऐसा नहीं है तो यह सुनिश्चित करने के लिए आवश्यक है कि स्ट्रिंग HTML सुरक्षित हो जाती है और परिणाम देता है।

जब आप escape_javascript का उपयोग कर रहे हैं, तो आमतौर पर इसे अन्य स्ट्रिंग या मौजूदा एचटीएमएल के भीतर एम्बेडेड किया जा रहा है। आपको यह सुनिश्चित करने की ज़रूरत है कि ऐसा करने से आपका पूरा पृष्ठ प्रस्तुत नहीं होगा।

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

मैंने कहा कि मैं इनकार नहीं कर रहा हूं कि स्क्रिप्ट इंजेक्शन संभव नहीं है। लेकिन इससे बचने के लिए जब आप उपयोगकर्ता डेटा लेते हैं और इसे अपने डेटाबेस में संग्रहीत करते हैं तो आपको कदम उठाने की आवश्यकता होती है। आपके द्वारा प्रदान किए जा रहे फ़ंक्शन और उदाहरण जानकारी को प्रतिपादित करने से संबंधित हैं, जो पहले से ही सहेजा गया था।

मुझे आशा है कि यह आपके प्रश्न की सहायता और उत्तर देगा।

संबंधित मुद्दे