मेरे पास एक वेब आधारित परियोजना है जो उपयोगकर्ताओं को ऑनलाइन और ऑफलाइन दोनों तरीके से काम करने की अनुमति देती है और मैं ग्राहक पक्ष पर रिकॉर्ड के लिए अद्वितीय आईडी उत्पन्न करने का तरीका ढूंढ रहा हूं। मैं एक दृष्टिकोण चाहता हूं जो एक उपयोगकर्ता के ऑफ़लाइन होने पर काम करता है (यानी सर्वर से बात करने में असमर्थ), अद्वितीय होने की गारंटी है, और सुरक्षित है। "सुरक्षित" द्वारा, मैं विशेष रूप से डुप्लिकेट आईडी (दुर्भावनापूर्ण या अन्यथा) सबमिट करने वाले ग्राहकों के बारे में चिंतित हूं और इस तरह डेटा अखंडता के लिए कहर बरपा रहा हूं।
मैं कुछ गुगली कर रहा हूं, उम्मीद है कि यह पहले से ही एक समस्या थी। मुझे ऐसा कुछ भी नहीं मिला है जो विशेष रूप से उत्पादन प्रणालियों में उपयोग किए जाने वाले दृष्टिकोणों के संदर्भ में बहुत निश्चित है। मुझे सिस्टम के लिए कुछ उदाहरण मिले जहां उपयोगकर्ता केवल उन डेटा तक पहुंच बनाएंगे जो उन्होंने बनाए हैं (जैसे कि एक टोडो सूची जो कई उपकरणों पर एक्सेस की जाती है, लेकिन केवल उस उपयोगकर्ता द्वारा बनाई गई है जिसने इसे बनाया है)। दुर्भाग्य से, मुझे कुछ अधिक परिष्कृत की आवश्यकता है। मुझे यहां कुछ बहुत अच्छे विचार मिले , जो इस बात के अनुरूप हैं कि मैं सोच रहा था कि चीजें कैसे काम कर सकती हैं।
नीचे मेरा प्रस्तावित समाधान है।
कुछ आवश्यकताएँ
- आईडी विश्व स्तर पर अद्वितीय होनी चाहिए (या सिस्टम के भीतर कम से कम अद्वितीय)
- ग्राहक पर उत्पन्न (यानी ब्राउज़र में जावास्क्रिप्ट के माध्यम से)
- सुरक्षित (ऊपर उल्लिखित और अन्यथा)
- डेटा को कई उपयोगकर्ताओं द्वारा देखा / संपादित किया जा सकता है, जिसमें वे उपयोगकर्ता भी शामिल हैं जिन्होंने इसे लेखक नहीं किया
- बैकएंड db (जैसे MongoDB या CouchDB) के लिए महत्वपूर्ण प्रदर्शन समस्याएँ पैदा नहीं करता है
प्रस्तावित समाधान
जब उपयोगकर्ता एक खाता बनाते हैं, तो उन्हें एक यूआईडी दिया जाएगा जो सर्वर द्वारा उत्पन्न किया गया था और सिस्टम के भीतर अद्वितीय होने के लिए जाना जाता था। यह आईडी उपयोगकर्ताओं के प्रमाणीकरण टोकन के समान नहीं होनी चाहिए। चलिए इस आईडी को यूजर्स "id token" कहते हैं।
जब कोई उपयोगकर्ता एक नया रिकॉर्ड बनाता है, तो वे जावास्क्रिप्ट में एक नया यूआईडी बनाते हैं (जब उपलब्ध विंडो। क्रिप्टो का उपयोग करके उत्पन्न होता है। यहां उदाहरण देखें )। इस आईडी को "आईडी टोकन" के साथ मिलाया जाता है जब उपयोगकर्ता ने अपना खाता बनाया था। यह नई समग्र आईडी (सर्वर साइड आईडी टोकन + क्लाइंट साइड यूआईडी) अब रिकॉर्ड के लिए अद्वितीय पहचानकर्ता है। जब उपयोगकर्ता ऑनलाइन होता है और बैकएंड सर्वर पर इस नए रिकॉर्ड को जमा करता है, तो सर्वर होगा:
- इसे "इन्सर्ट" एक्शन के रूप में पहचानें (अर्थात अपडेट या डिलीट नहीं)
- संयुक्त कुंजी के दोनों हिस्सों को मान्य uuids मान्य हैं
- सत्यापित करें कि समग्र आईडी का प्रदान किया गया "आईडी टोकन" वर्तमान उपयोगकर्ता के लिए सही है (अर्थात यह उपयोगकर्ता द्वारा असाइन किए गए सर्वर से आईडी टोकन से मेल खाता है जब उन्होंने अपना खाता बनाया था)
- यदि सब कुछ डाटाबेस में copasetic, डेटा डालने है (सावधान किया जा रहा है एक डालने और नहीं एक "Upsert" ऐसा करने के लिए इतना है कि यदि आईडी करता है पहले से मौजूद है यह गलती से एक मौजूदा रिकॉर्ड को अपडेट नहीं करता है)
क्वेरी, अपडेट और डिलीट को किसी विशेष तर्क की आवश्यकता नहीं होगी। वे बस पारंपरिक अनुप्रयोगों के रूप में रिकॉर्ड के लिए आईडी का उपयोग करेंगे।
इस दृष्टिकोण के क्या फायदे हैं?
क्लाइंट कोड ऑफ़लाइन रहते हुए नया डेटा बना सकता है और उस रिकॉर्ड के लिए आईडी को तुरंत जान सकता है। मैं वैकल्पिक दृष्टिकोणों पर विचार करता था, जहां क्लाइंट पर एक अस्थायी आईडी बनाई जाएगी जिसे बाद में सिस्टम के ऑनलाइन होने पर "फाइनल" आईडी के लिए स्वैप किया जाएगा। हालांकि, यह बहुत भंगुर लगा। खासकर जब आप विदेशी कुंजी के साथ बाल डेटा बनाने के बारे में सोचना शुरू करते हैं, जिसे अद्यतन करने की भी आवश्यकता होती है। उन यूआरएल से निपटने का उल्लेख नहीं है जो आईडी बदलने पर बदल जाएंगे।
आईडी को क्लाइंट जनरेटेड वैल्यू और सर्वर जनरेट वैल्यू का एक संयोजन बनाकर, प्रत्येक उपयोगकर्ता प्रभावी रूप से सैंडबॉक्स में आईडी बना रहा है। यह एक दुर्भावनापूर्ण / दुष्ट ग्राहक द्वारा किए जा सकने वाले नुकसान को सीमित करने के लिए है। इसके अलावा, कोई भी आईडी टकराव प्रति उपयोगकर्ता के आधार पर होता है, न कि पूरी प्रणाली के लिए वैश्विक।
चूंकि एक यूजर आईडी टोकन उनके खाते से जुड़ा हुआ है, इसलिए आईडी केवल एक उपयोगकर्ता सैंडबॉक्स में उन ग्राहकों द्वारा उत्पन्न की जा सकती है जो प्रमाणित हैं (यानी जहां उपयोगकर्ता सफलतापूर्वक लॉग इन किया गया है)। यह एक उपयोगकर्ता के लिए खराब आईडी बनाने से दुर्भावनापूर्ण क्लाइंट रखने का इरादा है। बेशक अगर किसी उपयोगकर्ता के टोकन को दुर्भावनापूर्ण क्लाइंट द्वारा चोरी किया गया था, तो वे खराब काम कर सकते हैं। लेकिन, एक बार एक टोकन के चोरी हो जाने पर खाता किसी भी तरह से समझौता कर लिया जाता है। ऐसा होने की स्थिति में, जो नुकसान हुआ है वह समझौता किए गए खाते (संपूर्ण प्रणाली नहीं) तक सीमित होगा।
चिंताओं
इस दृष्टिकोण के साथ मेरी कुछ चिंताएं हैं
क्या यह बड़े पैमाने पर आवेदन के लिए पर्याप्त रूप से अद्वितीय आईडी उत्पन्न करेगा? क्या यह सोचने का कोई कारण है कि इसके परिणामस्वरूप आईडी टकराव होगा? क्या जावास्क्रिप्ट इस काम के लिए एक पर्याप्त यादृच्छिक यूआईडी उत्पन्न कर सकता है? ऐसा लगता है कि window.crypto काफी व्यापक रूप से उपलब्ध है और इस परियोजना के लिए पहले से ही काफी आधुनिक ब्राउज़रों की आवश्यकता है। ( इस सवाल का अब एक अलग SO प्रश्न है )
क्या कोई खामी है जो मुझे याद आ रही है जो किसी दुर्भावनापूर्ण उपयोगकर्ता को सिस्टम से समझौता करने की अनुमति दे सकती है?
क्या 2 uuids से बनी कंपोजिट कुंजी की क्वेरी करते समय DB प्रदर्शन के बारे में चिंता करने का कारण है। सर्वश्रेष्ठ प्रदर्शन के लिए इस आईडी को कैसे संग्रहीत किया जाना चाहिए? दो अलग-अलग फ़ील्ड या एक ऑब्जेक्ट फ़ील्ड? क्या मोंगो बनाम काउच के लिए एक अलग "सर्वश्रेष्ठ" दृष्टिकोण होगा? मुझे पता है कि आवेषण करते समय एक गैर-अनुक्रमिक प्राथमिक कुंजी होने से उल्लेखनीय प्रदर्शन मुद्दे हो सकते हैं। क्या प्राथमिक कुंजी के लिए एक ऑटो उत्पन्न मूल्य रखना और इस आईडी को एक अलग क्षेत्र के रूप में संग्रहित करना बेहतर होगा? ( इस सवाल का अब एक अलग SO प्रश्न है )
इस रणनीति के साथ, यह निर्धारित करना आसान होगा कि रिकॉर्ड का एक विशेष सेट एक ही उपयोगकर्ता द्वारा बनाया गया था (क्योंकि वे सभी समान रूप से दृश्यमान आईडी टोकन साझा करेंगे)। हालांकि मुझे इसके साथ कोई तात्कालिक समस्या नहीं दिखती है, लेकिन आंतरिक विवरण के बारे में अधिक जानकारी लीक न करना हमेशा बेहतर होता है। एक और संभावना समग्र कुंजी हैश करने की होगी, लेकिन ऐसा लगता है कि यह मूल्य की तुलना में अधिक परेशानी हो सकती है।
इस घटना में कि उपयोगकर्ता के लिए एक आईडी टकराव है, ठीक होने का एक सरल तरीका नहीं है। मुझे लगता है कि ग्राहक एक नई आईडी तैयार कर सकता है, लेकिन यह एक किनारे मामले के लिए बहुत काम की तरह लगता है जो वास्तव में कभी नहीं होना चाहिए। मैं इस अभागे को छोड़ने का इरादा कर रहा हूं।
केवल प्रमाणित उपयोगकर्ता ही डेटा देख और / या संपादित कर सकते हैं। यह मेरे सिस्टम के लिए एक स्वीकार्य सीमा है।
निष्कर्ष
एक उचित योजना से ऊपर है? मुझे लगता है कि इसमें से कुछ को निर्णय में आवेदन की पूरी समझ के आधार पर एक निर्णय कॉल के लिए आता है।