कस्टम स्क्रिप्ट के लिए क्रॉस-ब्राउज़र वेब एक्सटेंशन भाग 3

इस लेख में, मैंने प्रकाशनों की श्रृंखला जारी रखी है जिसमें मैं अपने अनुभव को ब्राउज़रों के लिए वेब एक्सटेंशन लिखने के बारे में बात करना चाहता हूं। मेरे पास पहले से ही एक वेब एक्सटेंशन बनाने का अनुभव था, जो लगभग 100,000 क्रोम उपयोगकर्ताओं द्वारा स्थापित किया गया था, जो स्वायत्तता से काम करता था, लेकिन लेखों की इस श्रृंखला में मैंने सर्वर साइड के साथ इसे कसकर एकीकृत करके वेब एक्सटेंशन के विकास की प्रक्रिया में देरी करने का फैसला किया।

छविछविछविछविछवि

भाग 1 , भाग 2 , भाग 4

वेब एक्सटेंशन और सर्वर साइड की बातचीत को लागू करने में नुकसान


जैसा कि पहले ही बताया जा चुका है, सर्वर साइड Meteor.js का उपयोग करता है। RESTful API को कार्यान्वित करने के लिए, github.com/kahmali/meteor-restivus पैकेज का उपयोग किया जाता है। प्राधिकरण से संबंधित उपयोगकर्ता तंत्र को कवर करने के लिए इसमें पहले से ही कुछ कार्यान्वित भाग है।

उदाहरण के लिए, यह निर्दिष्ट करना पर्याप्त है : नीचे दिए गए उदाहरण के अनुसार, सच है , ताकि एपीआई बिंदु केवल अधिकृत उपयोगकर्ताओं के लिए काम करे।

Api.addRoute('clientScript/:id_script', {authRequired: true}, {get: { action: function() { //method for GET on htts://example.com/api/v1/clientScript/:id_script } }); 

इस प्रकार, तीन एपीआई बिंदु पंजीकरण के लिए जोड़े गए, प्रोफाइल डेटा प्राप्त करने और इसे अपडेट करने के लिए, पासवर्ड रीसेट के लिए।

वेब एक्सटेंशन में, जब प्राधिकरण की आवश्यकता होती है, तो कॉलिंग विधियों का उपयोग किया जाता है:

 var details = { url: API_URL + '/api/v1/clientDataRowDownload/' + dataRowId + '/download', method: 'GET', contentType: 'json', headers: {'X-Auth-Token': kango.storage.getItem("authToken"), 'X-User-Id': kango.storage.getItem("userId")} }; kango.xhr.send(details, function(data) { //code for response handler }) 

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

वेब एक्सटेंशन में फ़ाइलें डाउनलोड करना ब्राउज़र साइड पर फ़ाइल को पढ़ने और XHR के माध्यम से भेजने के द्वारा किया जाता है:

 $("form#uploadFile").on("submit", function(event, template) { event.preventDefault(); var reader = new FileReader(); reader.onload = function(evt) { var details = { url: API_URL + '/api/v1/clientFileAdd/' + kango.storage.getItem("userId"), method: 'POST', contentType: 'json', params: {"content": encodeURIComponent(evt.target.result.replace(/^data:[^;]*;base64,/, "")), "name": encodeURIComponent(event.currentTarget.fileInput.files[0].name), "size": event.currentTarget.fileInput.files[0].size, "type": event.currentTarget.fileInput.files[0].type, "lastModified": event.currentTarget.fileInput.files[0].lastModified }, headers: {'X-Auth-Token': kango.storage.getItem("authToken"), 'X-User-Id': kango.storage.getItem("userId")} }; kango.xhr.send(details, function(data) { if (data.status == 200 && data.response != null) { if(data.response.status == "success") { //ok } else { //error } } else { if(data.status == 401) { //notAuth } else { //error } } }); }; if (event.currentTarget.fileInput.files.length != 0) { reader.readAsDataURL(event.currentTarget.fileInput.files[0]); } return false; }); 

लाइन इवेंट को ध्यान में रखना महत्वपूर्ण है। target.result.replace (/ ^ डेटा: [^?] 4. बेस; 64, /, "") । ब्राउजर की तरफ की फाइल बेस 64 में इनकोडेड है, लेकिन बफरिंग में इस एन्कोडिंग का उपयोग करते समय सर्वर साइड पर कम्पैटिबिलिटी के लिए। नई लाइन (नई स्ट्रिंग (this.bodyParams.content), "बेस 64") हमें एन्कोडिंग उपसर्ग को काट देना चाहिए और फाइल के केवल "बॉडी" को पढ़ना चाहिए। । एन्कोडर्इकोम्पोनेंट में रैपिंग को नोट करना भी आवश्यक है, क्योंकि अक्सर आधार + और फ़ाइल नामों में समान + पाया जाता है।

स्क्रिप्ट संपादित करते समय, सामग्री को स्थानांतरित करते समय आपको स्क्रिप्ट के शरीर में वर्ण एन्कोडिंग पर विचार करना होगा। कुछ मामलों में, base64 एन्कोडिंग ने एन्कोडर्कोम्पोनेंट का उपयोग करते हुए सर्वर साइड पर डिकोड करने पर सही परिणाम नहीं दिया। इसलिए, utf8 में मजबूर एन्कोडिंग utf8.encode (str) के साथ पहले से उपयोग किया जाता है; @mathias से mths.be/utf8js v3.0.0

फ़ाइल डाउनलोड अच्छी तरह से स्थापित FileSaver लाइब्रेरी का उपयोग करके कार्यान्वित किया जाता है। XHR के माध्यम से प्राप्त डेटा को बस फ़ाइल कंस्ट्रक्टर के इनपुट में स्थानांतरित किया जाता है, और फिर फ़ाइल डाउनलोड को प्रारंभ किया जाता है:

 var file = new File([data.response.data.join("\n")], "data_rows" + date.getFullYear() + "_" + (date.getMonth() + 1) + "_" + date.getDate() + ".csv", {type: "application/vnd.ms-excel"}); saveAs(file); 

कस्टम स्क्रिप्ट के लिए आंतरिक पुस्तकालय


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

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

कई साइटें अपने वेब सेवाओं के पृष्ठों पर मनमाने ढंग से जावास्क्रिप्ट कोड के निष्पादन से बचाने के लिए CSP हेडर का उपयोग करती हैं, इस प्रकार वेब ब्राउज़र साइड पर XSS से खुद को बचाती हैं।

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

एक सीएसपी नीति प्रतिबंध को कंगो ढांचे का उपयोग करके निम्नलिखित तरीके से लागू किया जा सकता है:

 var browserObject; if(kango.browser.getName() == 'chrome') { browserObject = chrome; } else { browserObject = browser; } var filter = { urls: ["*://*/*"], types: ["main_frame", "sub_frame"] }; var onHeadersReceived = function(details) { var newHeaders = []; for (var i = 0; i < details.responseHeaders.length; i++) { if ('content-security-policy' !== details.responseHeaders[i].name.toLowerCase() && 'x-xss-protection' !== details.responseHeaders[i].name.toLowerCase() ) { newHeaders.push(details.responseHeaders[i]); } } return { responseHeaders: newHeaders }; }; browserObject.webRequest.onHeadersReceived.addListener(onHeadersReceived, filter, ["blocking", "responseHeaders"]); 

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

 "permissions": { ... "webRequest": true, "webRequestBlocking": true, ... } 

CSP द्वारा लगाए गए प्रतिबंधों के साथ समस्या को हल करने के बाद, उपयोगकर्ता इंटरनेट पर किसी भी पृष्ठ पर उसके द्वारा लिखी गई लिपियों का उपयोग कर सकता है।

आंतरिक पुस्तकालय से कॉलिंग फ़ंक्शन वैश्विक Gc ऑब्जेक्ट के माध्यम से उपलब्ध है।
वर्तमान में कार्यान्वित कार्य:

  • GC.saveRow (नाम, सामग्री, [फिर से लिखना = 0, async = false]); , जहां नाम संग्रह को लिखने के लिए लाइनों का नाम है, लेखन के लिए सामग्री स्वयं डेटा लाइन है, फिर से लिखना पूरे संग्रह को अधिलेखित करने के लिए ध्वज है, जिसका उपयोग Gc.saveRow (नाम, 'स्पष्ट', 1) में किया गया है; जो स्ट्रिंग संग्रह में सभी प्रविष्टियों को हटाता है, एसिंक्रोन अतुल्यकालिक मोड में काम करने के लिए एक झंडा है।
  • GC.getRows (नाम, संख्या, [गिनती = 1, async = false]); जहां नाम संग्रह में लाइनों का नाम है, संख्या डेटा प्राप्त करने के लिए लाइन की क्रम संख्या है, गिनती संख्या के साथ शुरू होने वाले डेटा की संख्या है, एसिंक्रोन अतुल्यकालिक मोड में काम करने के लिए ध्वज है।
  • GC.console (स्ट्रिंग); , जहां स्ट्रिंग उस पृष्ठ पर GC कंसोल के आउटपुट के लिए एक स्ट्रिंग है जहां स्क्रिप्ट निष्पादित होती है। उदाहरण के लिए, किसी कार्य की प्रगति को प्रदर्शित करने के लिए।
  • GC.clearConsole (); फ़ंक्शन उस पृष्ठ पर GC कंसोल को साफ़ करता है जहां स्क्रिप्ट निष्पादित होती है।
  • GC.stopScript (); , स्क्रिप्ट निष्पादन को रोकने के लिए कार्य करता है।
  • GC.loadFile (नाम, [parseAs = text]); , जहां नाम उस फ़ाइल का नाम है, जिसके विस्तार के लिए आप जिस सामग्री को प्राप्त करना चाहते हैं, वह पार्स डेटा पूर्वप्रक्रमक प्रारूप है, वर्तमान में json और पाठ समर्थित हैं।

अगले लेख में मैं " निर्धारित कार्यों " के बारे में बात करूँगा।

Source: https://habr.com/ru/post/hi416585/


All Articles