डोम में JSON एम्बेड करने के लिए सबसे अच्छा अभ्यास?


110

मैं इस तरह से DOM में मनमानी JSON को एम्बेड करने के बारे में सोच रहा हूं:

<script type="application/json" id="stuff">
    {
        "unicorns": "awesome",
        "abc": [1, 2, 3]
    }
</script>

यह उसी तरह है जैसे कोई एक जावास्क्रिप्ट टेम्पलेट इंजन के साथ बाद में उपयोग के लिए DOM में एक मनमाना HTML टेम्पलेट संग्रहीत कर सकता है। इस मामले में, हम बाद में JSON को पुनः प्राप्त कर सकते हैं और इसके साथ पार्स कर सकते हैं:

var stuff = JSON.parse(document.getElementById('stuff').innerHTML);

यह काम करता है , लेकिन क्या यह सबसे अच्छा तरीका है? क्या यह किसी सर्वोत्तम अभ्यास या मानक का उल्लंघन करता है?

नोट: मैं JSON को DOM में संग्रहीत करने के लिए विकल्पों की तलाश नहीं कर रहा हूं, मैंने पहले ही तय कर लिया है कि मुझे जो विशेष समस्या हो रही है उसके लिए सबसे अच्छा समाधान है। मैं इसे करने का सबसे अच्छा तरीका ढूंढ रहा हूं।


1
आपके पास varजावास्क्रिप्ट में यह क्यों नहीं होगा ?
क्रिज़

@ क्रिज़, इसे एक स्थिर दस्तावेज़ का हिस्सा होने की आवश्यकता है जिसे बाद में एन्कैप्सुलेटेड जावास्क्रिप्ट की एक जटिल श्रृंखला द्वारा संसाधित किया जाता है। इसे DOM में स्टोर करना है जो मैं करना चाहता हूं।
बेन ली

@ क्रिज I को इसी तरह की समस्या के साथ रखा गया था। मैं AJAX अनुरोध किए बिना प्रत्येक उपयोगकर्ता के लिए अलग साइट में डेटा डालना चाहता था। इसलिए मैंने कुछ PHP को एक कंटेनर में एम्बेड किया, जो कि आपके पास जावास्क्रिप्ट में डेटा प्राप्त करने के लिए ऊपर के समान कुछ था।
पैट्रिक लोरियो

2
मुझे लगता है कि आपका मूल तरीका वास्तव में सबसे अच्छा है। यह HTML5 में 100% वैध है, यह अर्थपूर्ण है, यह "नकली" तत्व नहीं बनाता है जिसे आप सीएसएस के साथ हटा देंगे या छिपा देंगे; और इसके लिए किसी वर्ण एन्कोडिंग की आवश्यकता नहीं है। नकारात्मक पक्ष क्या है?
जेमी ट्रैवेरी

22
यदि </script><script>alert()</script><script>आपके JSON ऑब्जेक्ट के अंदर मान के साथ एक स्ट्रिंग है , तो आपको आश्चर्य होगा। यह तब तक सुरक्षित नहीं है जब तक आप पहले डेटा को सुरक्षित नहीं करते हैं।
सिल्वोट

जवाबों:


77

मुझे लगता है कि आपका मूल तरीका सबसे अच्छा है। HTML5 कल्पना भी इस उपयोग को संबोधित करती है:

"जब डेटा ब्लॉक (स्क्रिप्ट के विपरीत) शामिल करने के लिए उपयोग किया जाता है, तो डेटा को इनलाइन एम्बेड किया जाना चाहिए, डेटा का प्रारूप टाइप विशेषता का उपयोग करके दिया जाना चाहिए, src विशेषता निर्दिष्ट नहीं होनी चाहिए, और स्क्रिप्ट तत्व की सामग्री होनी चाहिए उपयोग किए गए प्रारूप के लिए परिभाषित आवश्यकताओं के अनुरूप। "

यहां पढ़ें: http://dev.w3.org/html5/spec/Overview.html#the-script-element

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


3
धन्यवाद। युक्ति के उद्धरण ने मुझे आश्वस्त किया है।
बेन ली

17
यह पूरी तरह से केवल तभी मान्य होता है जब आप पहले JSON ऑब्जेक्ट को चेक और सैनिटाइज़ करते हैं: आप केवल उपयोगकर्ता के मूल डेटा को एम्बेड नहीं कर सकते। सवाल पर मेरी टिप्पणी देखें।
सिल्वोट

1
अतिरिक्त सोच: इसे लगाने के लिए अच्छी जगह कौन सी है? सिर या शरीर, ऊपर या नीचे?
चैलेट

1
दुर्भाग्य से, ऐसा प्रतीत होता है कि CSP नीति सभी scriptटैग को रोक / सकती है ।
लैरी के

2
आप JSON को एम्बेड करने से प्रभावी रूप से कैसे पहरा देते हैं जिसमें </ script> है और इस प्रकार, HTML इंजेक्शन की अनुमति देता है? क्या कुछ ठोस / आसान है, या डेटा विशेषताओं का उपयोग करना बेहतर है?
jonasfj

23

एक सामान्य दिशा के रूप में, मैं इसके बजाय HTML5 डेटा विशेषताओं का उपयोग करने का प्रयास करूंगा । आपको वैध JSON में डालने से रोकने के लिए कुछ भी नहीं है। उदाहरण के लिए:

<div id="mydiv" data-unicorns='{"unicorns":"awesome", "abc":[1,2,3]}' class="hidden"></div>

यदि आप jQuery का उपयोग कर रहे हैं, तो इसे पुनः प्राप्त करना उतना ही आसान है:

var stuff = JSON.parse($('#mydiv').attr('data-unicorns'));

1
समझ में आता है। हालांकि ध्यान दें कि प्रमुख नाम के लिए एकल उद्धरण के साथ, JSON.parseकाम नहीं करेगा (कम से कम मूल Google Chrome JSON.parse नहीं होगा)। JSON युक्ति को दोहरे उद्धरण चिह्नों की आवश्यकता होती है। लेकिन यह इतना आसान है जैसे संस्थाओं का उपयोग करना ...&lt;unicorns&gt;:...
बेन ली

4
हालांकि एक सवाल: क्या HTML 5 में विशेषताओं की लंबाई की कोई सीमा है?
बेन ली

हाँ, यह काम करेगा। आप इसे भी इधर-उधर कर सकते हैं ताकि आपका HTML एकल उद्धरणों का उपयोग करे और JSON डेटा डबल का उपयोग करे।
होरेशियो एल्डेरन

1
ठीक है, मेरे प्रश्न का उत्तर मिला: stackoverflow.com/questions/1496096/… - यह मेरे उद्देश्यों के लिए पर्याप्त है।
बेन ली

2
यह एक स्ट्रिंग के लिए काम नहीं करेगा, जैसे "I am valid JSON"टैग के लिए दोहरे उद्धरण चिह्नों का उपयोग करना, या स्ट्रिंग में एकल उद्धरण के साथ एकल उद्धरण, जैसे data-unicorns='"My JSON's string"'कि एकल उद्धरण JSON के रूप में एन्कोडिंग के साथ बच नहीं रहे हैं।
रॉबी एवरिल

13

स्क्रिप्ट टैग में जेंस एम्बेड करने की इस विधि में एक संभावित सुरक्षा समस्या है। उपयोगकर्ता इनपुट से उत्पन्न जसन डेटा को मानते हुए, एक डेटा सदस्य को तैयार करना संभव है जो स्क्रिप्ट टैग से बाहर निकल जाएगा और डोम में सीधे इंजेक्शन की अनुमति देगा। यहाँ देखें:

http://jsfiddle.net/YmhZv/1/

यहाँ इंजेक्शन है

<script type="application/json" id="stuff">
{
    "unicorns": "awesome",
    "abc": [1, 2, 3],
    "badentry": "blah </script><div id='baddiv'>I should not exist.</div><script type="application/json" id='stuff'> ",
}
</script>

भागने / एनकोडिंग के आसपास कोई रास्ता नहीं है।


7
यह सच है, लेकिन यह वास्तव में विधि का सुरक्षा दोष नहीं है। यदि आप कभी भी कुछ ऐसा बनाते हैं जो आपके पृष्ठों में उपयोगकर्ता इनपुट में उत्पन्न होता है, तो आपको इसे बचने के बारे में मेहनती होना होगा। जब तक आप उपयोगकर्ता इनपुट के बारे में सामान्य एहतियाती उपाय करते हैं तब तक यह विधि अभी भी ध्वनि है।
बेन ली

JSON HTML का हिस्सा नहीं है, HTML पार्सर बस चलता रहता है। यह वैसा ही है जब JSON एक टेक्स्ट पैराग्राफ या डिवा-एलिमेंट का हिस्सा होगा। HTML- अपने प्रोग्राम में कंटेंट से बचकर रहें। इसके अलावा, आप स्लैश से भी बच सकते हैं। जबकि JSON को इसकी आवश्यकता नहीं है, लेकिन यह अनावश्यक स्लैश को सहन नहीं करता है। जिसका उपयोग उसे एम्बेड करने के लिए सुरक्षित बनाने के उद्देश्य से किया जा सकता है। PHP का json_encode डिफ़ॉल्ट रूप से ऐसा करता है।
टिमो तिजहोफ

7

OWASP की XSS रोकथाम धोखा शीट में नियम # 3.1 देखें ।

आप इस JSON को HTML में शामिल करना चाहते हैं:

{
    "html": "<script>alert(\"XSS!\");</script>"
}

<div>HTML में छिपा हुआ बनाएँ । अगला, असुरक्षित संस्थाओं (जैसे, और, <,>, ", ', और, /) एन्कोडिंग द्वारा अपने JSON से बचकर तत्व के अंदर रखें।

<div id="init_data" style="display:none">
        {&#34;html&#34;:&#34;&lt;script&gt;alert(\&#34;XSS!\&#34;);&lt;/script&gt;&#34;}
</div>

अब आप textContentजावास्क्रिप्ट का उपयोग करने वाले तत्व को पढ़कर और इसे पार्स करके इसे एक्सेस कर सकते हैं :

var text = document.querySelector('#init_data').textContent;
var json = JSON.parse(text);
console.log(json); // {html: "<script>alert("XSS!");</script>"}

मेरा मानना ​​है कि यह सबसे अच्छा और सबसे सुरक्षित जवाब है। ध्यान दें कि बहुत से सामान्य JSON अक्षर बच जाते हैं, और कुछ अक्षर डबल बच जाते हैं, जैसे कि ऑब्जेक्ट में आंतरिक उद्धरण {name: 'Dwayne "The Rock" Johnson'}। लेकिन संभवतः यह अभी भी इस दृष्टिकोण का उपयोग करना सबसे अच्छा है क्योंकि आपकी रूपरेखा / टेम्प्लेटिंग लाइब्रेरी की संभावना पहले से ही HTML एन्कोडिंग करने का एक सुरक्षित तरीका शामिल है। एक विकल्प बेस 64 का उपयोग करना होगा जो जेएस स्ट्रिंग के अंदर डालने के लिए HTML सुरक्षित और सुरक्षित दोनों है। जेएस में btoa () / atob () का उपयोग करना सांकेतिक शब्दों में बदलना / डिकोड करना आसान है और संभवतः आपके लिए सर्वर साइड करना आसान है।
शाम

यहां तक ​​कि एक सुरक्षित तरीका शब्दार्थ रूप से सही <data>तत्व का उपयोग करना होगा और JSON डेटा को valueविशेषता में शामिल करना होगा। तब आपको केवल उद्धरण चिह्नों से बचने की आवश्यकता होती है &quotयदि आप डेटा को संलग्न करने के लिए दोहरे उद्धरण चिह्नों का उपयोग करते हैं, या &#39;यदि आप एकल उद्धरणों का उपयोग करते हैं (जो शायद बेहतर है)।
रूनर बर्ग

5

मैं JSON को एक इनलाइन स्क्रिप्ट में फ़ंक्शन कॉलबैक ( JSONP का प्रकार ) के साथ डालने का सुझाव दूंगा :

<script>
someCallback({
    "unicorns": "awesome",
    "abc": [1, 2, 3]
});
</script>

यदि निष्पादित स्क्रिप्ट को दस्तावेज़ के बाद लोड किया जाता है, तो आप इसे कहीं और स्टोर कर सकते हैं, संभवतः एक अतिरिक्त पहचानकर्ता तर्क के साथ: someCallback("stuff", { ... });


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

यह बेहतर लगता है क्योंकि आपको डेटा खोजने के लिए डोम क्वेरी की आवश्यकता नहीं है
जस्सीम

@copy इस समाधान को अभी भी भागने की ज़रूरत है (बस एक अलग तरह का), मैडकोडर का जवाब देखें। बस इसे पूर्णता के लिए यहां छोड़ रहे हैं।
पवरगान

2

मेरी सिफारिश होगी कि JSON डेटा को बाहरी .jsonफ़ाइलों में रखा जाए, और फिर उन फ़ाइलों को अजाक्स के माध्यम से पुनः प्राप्त किया जाए। आप वेब-पेज (इनलाइन) पर CSS और JavaScript कोड नहीं डालते हैं, तो आप JSON के साथ ऐसा क्यों करेंगे?


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

ऐसा इसलिए है क्योंकि मैं एक ऐसी विरासत प्रणाली को अपडेट कर रहा हूं जिसे खराब तरीके से डिजाइन किया गया था, और पूरे सिस्टम को नया स्वरूप देने के बजाय, मुझे केवल एक भाग को ठीक करने की आवश्यकता है। DOM में JSON को स्टोर करना इस एक हिस्से को ठीक करने का सबसे अच्छा तरीका है। साथ ही, @jamietre ने जो कहा, मैं उससे सहमत हूं।
बेन ली

@jamietre ध्यान दें कि ओपी ने कहा कि यह JSON स्ट्रिंग केवल बाद में आवश्यक है । सवाल यह है कि क्या यह हमेशा की जरूरत है, या केवल कुछ मामलों में। यदि यह केवल कुछ मामलों में आवश्यक है, तो इसका मतलब यह है कि इसे किसी बाहरी फ़ाइल में रखना है और केवल सशर्त लोड करना है।
23इमे विदा

2
मैं मानता हूं कि कई "क्या अगर" हैं जो पैमाने को एक या दूसरे तरीके से टिप कर सकते हैं। लेकिन आम तौर पर बोलते हुए अगर आप जानते हैं कि पेज को तब प्रस्तुत किया जाता है, जब आपको इसकी आवश्यकता होती है - भले ही संभवतः - यह अक्सर इसे तुरंत भेजना बेहतर होता है। जैसे, अगर मेरे पास कुछ सूचना बक्से थे जो ढहने लगते हैं, तो मैं आमतौर पर उनकी सामग्री इनलाइन को शामिल करना चाहता हूं ताकि वे तुरंत विस्तारित हो जाएं। ओवरहेड एक नया अनुरोध एक मौजूदा एक बिट अतिरिक्त डेटा के ओवरहेड की तुलना में बहुत अधिक है, और यह एक अधिक संवेदनशील डेटा अनुभव बनाता है। मुझे यकीन है कि एक विराम बिंदु है।
जेमी ट्रेवेरी

2

HTML5 में मशीन पठनीय डेटा रखने के लिए एक <data>तत्व शामिल है । एक के रूप में - शायद <script type="application/json">आप के लिए सुरक्षित - valueउस तत्व की विशेषता के अंदर अपने JSON डेटा शामिल कर सकते हैं ।

const jsonData = document.querySelector('.json-data');
const data = JSON.parse(jsonData.value);

console.log(data)
<data class="json-data" value='
  {
    "unicorns": "awesome",
    "abc": [1, 2, 3],
    "careful": "to escape &#39; quotes"
  }
'></data>

इस मामले में आपको सभी एकल उद्धरणों को प्रतिस्थापित करने की आवश्यकता होती है &#39;या &quot;यदि आप दोहरे उद्धरण चिह्नों के साथ मान संलग्न करना चुनते हैं। अन्यथा अन्य जोखिमों की तरह आपके जोखिम XSS हमलों ने सुझाव दिया है।

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