JSON वेब टोकन अमान्य करना


420

एक नए नोड.जेएस प्रोजेक्ट के लिए, जिस पर मैं काम कर रहा हूं, मैं कुकी आधारित सत्र दृष्टिकोण से स्विच करने के बारे में सोच रहा हूं (इसके द्वारा, मेरा मतलब है कि उपयोगकर्ता के ब्राउज़र में उपयोगकर्ता सत्र वाले कुंजी-मूल्य स्टोर में आईडी संग्रहीत करना) JSON वेब टोकन (jwt) का उपयोग करके टोकन-आधारित सत्र दृष्टिकोण (कोई कुंजी-मूल्य स्टोर) नहीं।

प्रोजेक्ट एक ऐसा गेम है जो सॉकेट का उपयोग करता है ।io - एक टोकन-आधारित सत्र होना ऐसे परिदृश्य में उपयोगी होगा जहां एक सत्र (वेब ​​और सॉकेट.आईओ) में कई संचार चैनल होंगे।

Jwt दृष्टिकोण का उपयोग करके सर्वर से टोकन / सत्र अमान्य कैसे प्रदान किया जाएगा?

मैं यह भी समझना चाहता था कि इस तरह के प्रतिमान के साथ मुझे क्या आम (या असामान्य) नुकसान / हमले देखने चाहिए। उदाहरण के लिए, यदि यह प्रतिमान सत्र स्टोर / कुकी-आधारित दृष्टिकोण के समान / विभिन्न प्रकार के हमलों के लिए असुरक्षित है।

तो, कहते हैं कि मेरे पास निम्नलिखित है ( इस और इस से अनुकूलित ):

सत्र स्टोर लॉगिन:

app.get('/login', function(request, response) {
    var user = {username: request.body.username, password: request.body.password };
    // Validate somehow
    validate(user, function(isValid, profile) {
        // Create session token
        var token= createSessionToken();

        // Add to a key-value database
        KeyValueStore.add({token: {userid: profile.id, expiresInMinutes: 60}});

        // The client should save this session token in a cookie
        response.json({sessionToken: token});
    });
}

टोकन-आधारित लॉगिन:

var jwt = require('jsonwebtoken');
app.get('/login', function(request, response) {
    var user = {username: request.body.username, password: request.body.password };
    // Validate somehow
    validate(user, function(isValid, profile) {
        var token = jwt.sign(profile, 'My Super Secret', {expiresInMinutes: 60});
        response.json({token: token});
    });
}

-

सत्र स्टोर दृष्टिकोण के लिए एक लॉगआउट (या अमान्य) निर्दिष्ट टोकन के साथ KeyValueStore डेटाबेस के लिए एक अद्यतन की आवश्यकता होगी।

ऐसा लगता है कि इस तरह का तंत्र टोकन-आधारित दृष्टिकोण में मौजूद नहीं होगा क्योंकि टोकन में ही वह जानकारी होगी जो सामान्य रूप से कुंजी-मूल्य स्टोर में मौजूद होगी।


1
यदि आप 'एक्सप्रेस- jwt' पैकेज का उपयोग कर रहे हैं, तो आप isRevokedविकल्प देख सकते हैं , या समान कार्यक्षमता को दोहराने का प्रयास कर सकते हैं। github.com/auth0/express-jwt#revoked-tokens
Signus

1
डेटाबेस में उपयोगकर्ता की पहुंच की स्थिति की जाँच करने (ब्लैकलिस्टिंग) के लिए अनुमति देने के लिए, लंबे समय तक रहने वाले समाप्ति के साथ, टोकन तक पहुँच समाप्ति और ताज़ा टोकन का उपयोग करने पर विचार करें। auth0.com/blog/...
Rohmer

एक अन्य विकल्प jwt टोकन उत्पन्न करते समय पेलोड में आईपी एड्रेस संलग्न करना होगा और समान आईपी पते के लिए संग्रहीत आईपी बनाम आने वाले अनुरोध की जांच करना होगा। पूर्व: req.connection.remoteAddress in नोडज। आईएसपी प्रदाता हैं जो प्रति ग्राहक स्थिर आईपी जारी नहीं करते हैं, मुझे लगता है कि यह तब तक समस्या नहीं होगी जब तक कि ग्राहक इंटरनेट से जुड़ता नहीं है।
गिहान सैंडारू

जवाबों:


391

मैं भी इस प्रश्न पर शोध कर रहा हूं, और नीचे दिए गए विचारों में से कोई भी पूर्ण समाधान नहीं है, वे दूसरों को विचारों को नियंत्रित करने में मदद कर सकते हैं, या आगे प्रदान कर सकते हैं।

1) बस क्लाइंट से टोकन निकालें

जाहिर है कि यह सर्वर साइड सिक्योरिटी के लिए कुछ नहीं करता है, लेकिन यह टोकन को अस्तित्व से हटाकर एक हमलावर को रोकता है (यानी उन्हें लॉगआउट से पहले टोकन को चोरी करना होगा)।

2) एक टोकन ब्लैकलिस्ट बनाएं

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

3) बस टोकन एक्सपायरी समय कम रखें और उन्हें अक्सर घुमाएं

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

आकस्मिक योजनाएं

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

मैं यह भी नोट करना चाहता था कि टोकन के साथ अंतिम लॉगिन तिथि को शामिल करना एक अच्छा विचार है, ताकि आप कुछ दूर की अवधि के बाद पुनः लागू करने में सक्षम हों।

टोकनों का उपयोग करने वाले हमलों के संबंध में समानताएं / मतभेदों के संदर्भ में, यह पोस्ट प्रश्न को संबोधित करती है: https://github.com/dentarg/blog/blob/master/_posts/2014-01-07-angularjs-authulication-with-cookies -vs-token.markdown


3
उत्कृष्ट दृष्टिकोण। मेरा आंत सभी 3 का संयोजन करना होगा, और / या, हर "एन" अनुरोध के बाद एक नया टोकन अनुरोध करें (जैसा कि टाइमर के विपरीत)। हम इन-मेमोरी ऑब्जेक्ट स्टोरेज के लिए रेडिस का उपयोग कर रहे हैं, और हम आसानी से केस # 2 के लिए इसका उपयोग कर सकते हैं, और फिर विलंबता नीचे चली जाएगी।
आरोन वैगनर

2
यह कोडिंग हॉरर पोस्ट कुछ सलाह देता है: सत्र सत्र कुकीज़ (या टोकन) को संक्षिप्त रखें लेकिन इसे उपयोगकर्ता के लिए अदृश्य बना दें - जो # 3 के अनुरूप प्रतीत होता है। मेरी खुद की आंत (शायद इसलिए कि यह अधिक पारंपरिक है) सिर्फ टोकन (या इसका एक हैश) है जो सफेद-सूचीबद्ध सत्र डेटाबेस (# 2 के समान) में एक कुंजी के रूप में कार्य करता है
funseiki

7
लेख अच्छी तरह से लिखा गया है, और ऊपर का एक विस्तृत संस्करण है 2)। हालांकि यह ठीक काम करता है, व्यक्तिगत रूप से मुझे पारंपरिक सत्र भंडारों में बहुत अंतर नहीं दिखता है। मुझे लगता है कि भंडारण की आवश्यकता कम होगी, लेकिन आपको अभी भी एक डेटाबेस की आवश्यकता है। मेरे लिए JWT की सबसे बड़ी अपील सत्रों के लिए डेटाबेस का उपयोग नहीं करना था।
मैट वे

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

4
एक ब्लैकलिस्ट को स्मृति में रखकर कुशल बनाया जा सकता है, ताकि डीबी को केवल रिकॉर्ड अमान्य करने के लिए मारा जाए और समाप्त अमान्य हटा दिया जाए और केवल सर्वर लॉन्च पर पढ़ें। लोड-बैलेंसिंग आर्किटेक्चर के तहत, इन-मेमरी ब्लैकलिस्ट डीबी को छोटे अंतराल पर, जैसे 10 के दशक में, अमान्य टोकन के संपर्क को सीमित कर सकता है। ये दृष्टिकोण सर्वर को डीबी पहुँच के बिना अनुरोधों को प्रमाणित करने की अनुमति देते हैं।
जो लैप

85

ऊपर पोस्ट किए गए विचार अच्छे हैं, लेकिन सभी मौजूदा JWTs को अमान्य करने का एक बहुत ही सरल और आसान तरीका बस रहस्य को बदलना है।

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

यह वास्तविक टोकन सामग्री (या लुकअप आईडी) के लिए किसी भी संशोधन की आवश्यकता नहीं है।

स्पष्ट रूप से यह केवल एक आपातकालीन स्थिति के लिए काम करता है जब आप सभी मौजूदा टोकन को समाप्त करना चाहते थे, टोकन समाप्ति के लिए ऊपर दिए गए समाधानों में से एक की आवश्यकता होती है (जैसे कि लघु टोकन समाप्ति समय या टोकन के अंदर संग्रहीत कुंजी को अमान्य करना)।


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

1
@KijanaWoodard, RS256 एल्गोरिथ्म में प्रभावी रूप से रहस्य के रूप में हस्ताक्षर को मान्य करने के लिए एक सार्वजनिक / निजी कुंजी जोड़ी का उपयोग किया जा सकता है। यहां दिखाए गए उदाहरण में उन्होंने JWT को अमान्य करने के लिए रहस्य को बदलने का उल्लेख किया है। यह या तो एक) एक नकली प्यूबिक को प्रस्तुत करने से किया जा सकता है जो हस्ताक्षर या बी से मेल नहीं खाता है) एक नया प्यूबिक उत्पन्न करता है। उस स्थिति में, यह आदर्श से कम है।
15

1
@ सिग्नस - गोच। सार्वजनिक कुंजी को गुप्त के रूप में उपयोग नहीं करना, लेकिन हस्ताक्षर को सत्यापित करने के लिए अन्य लोग सार्वजनिक कुंजी पर निर्भर हो सकते हैं।
किजाना वुडार्ड

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

5
@TuomasToivonen, लेकिन आपको एक JWT को एक गुप्त पर हस्ताक्षर करना चाहिए और उसी गुप्त के साथ JWT को सत्यापित करने में सक्षम होना चाहिए। इसलिए आपको संरक्षित संसाधनों पर रहस्य को संग्रहित करना चाहिए। यदि रहस्य से समझौता किया जाता है तो आपको इसे बदलना होगा और अपने प्रत्येक नोड में उस परिवर्तन को वितरित करना होगा। क्लस्टरिंग / स्केलिंग के साथ होस्टिंग प्रदाता आमतौर पर इन रहस्यों को आसान और विश्वसनीय वितरित करने के लिए आपको उनकी सेवा में रहस्यों को संग्रहीत करने की अनुमति देते हैं।
रोम्मर

67

यह मुख्य रूप से @mattway द्वारा उत्तर पर एक लंबी टिप्पणी का समर्थन और निर्माण है

दिया हुआ:

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

(यदि आपकी साइट को अनधिकृत अनुरोधों की एक उच्च मात्रा प्राप्त होती है, तो JWT उन्हें डेटास्टोर से टकराने के बिना इनकार कर देगा, जो सहायक है। शायद इस तरह के अन्य उपयोग के मामले हैं।)

दिया हुआ:

सचमुच स्टेटलेस JWT प्रमाणीकरण एक विशिष्ट, वास्तविक विश्व वेब ऐप के लिए प्राप्त नहीं किया जा सकता है क्योंकि स्टेटलेस JWT के पास निम्न महत्वपूर्ण उपयोग मामलों के लिए तत्काल और सुरक्षित समर्थन प्रदान करने का तरीका नहीं है :

उपयोगकर्ता का खाता हटा / अवरुद्ध / निलंबित कर दिया गया है।

उपयोगकर्ता का पासवर्ड बदल दिया गया है।

उपयोगकर्ता की भूमिकाएं या अनुमतियां बदली जाती हैं।

उपयोगकर्ता व्यवस्थापक द्वारा लॉग आउट किया गया है।

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

आप इन मामलों में टोकन समाप्ति की प्रतीक्षा नहीं कर सकते। टोकन अमान्य होना तुरंत होना चाहिए। इसके अलावा, आप ग्राहक पर भरोसा नहीं कर सकते हैं कि वह पुराने टोकन की प्रतिलिपि न रखें और उसका उपयोग न करें, चाहे वह दुर्भावनापूर्ण इरादे से हो या नहीं।

इसलिए: मुझे लगता है कि @ मैट-वे, # 2 टोकनब्लैकलिस्ट से उत्तर, JWT आधारित प्रमाणीकरण के लिए आवश्यक स्थिति को जोड़ने के लिए सबसे कुशल तरीका होगा।

आपके पास एक ब्लैक लिस्ट है जो इन टोकन को रखती है जब तक कि उनकी समाप्ति तिथि हिट नहीं होती है। उपयोगकर्ताओं की कुल संख्या की तुलना में टोकन की सूची काफी छोटी होगी, क्योंकि इसमें केवल समाप्ति तक ब्लैक लिस्टेड टोकन को रखना होगा। मैं रेडिस, मेम्केड या किसी अन्य इन-मेमोरी डाटस्टोर में अमान्य टोकन डालकर कार्यान्वित करूँगा जो एक कुंजी पर समाप्ति समय निर्धारित करने का समर्थन करता है।

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


15
मैं आपके उत्तर से सहमत नहीं हूँ। डेटाबेस को हिट करने से कुछ भी नहीं होता है; आपके बैकएंड पर स्टोरिंग स्टेट करता है। JWT इसलिए नहीं बनाया गया कि आपको प्रत्येक अनुरोध पर डेटाबेस को हिट न करना पड़े। JWT का उपयोग करने वाले प्रमुख एप्लिकेशन को डेटाबेस द्वारा समर्थित किया जाता है। JWT एक पूरी तरह से अलग समस्या हल करती है। en.wikipedia.org/wiki/Stateless_protocol
जूलियन

6
@ जूलियन आप इस पर थोड़ा विस्तार कर सकते हैं? JWT वास्तव में फिर किस समस्या का समाधान करता है?

8
@ zero01alpha प्रमाणीकरण: JWT का उपयोग करने के लिए यह सबसे आम परिदृश्य है। उपयोगकर्ता द्वारा लॉग इन करने के बाद, प्रत्येक बाद के अनुरोध में JWT शामिल होगा, जिससे उपयोगकर्ता रूट, सेवाओं और संसाधनों तक पहुँचने की अनुमति देता है जो उस टोकन के साथ अनुमत हैं। सूचना विनिमय: JSON वेब टोकन पार्टियों के बीच सुरक्षित रूप से संचारित जानकारी का एक अच्छा तरीका है। क्योंकि JWTs पर हस्ताक्षर किए जा सकते हैं आप सुनिश्चित कर सकते हैं कि प्रेषक वे हैं जो वे कहते हैं कि वे हैं। देखें jwt.io/introduction
जूलियन

7
@ जूलियन मैं आपकी असहमति से सहमत नहीं हूं :) JWT समस्या को हल करता है (सेवाओं के लिए) किसी भी क्लाइंट के लिए प्राधिकरण जानकारी प्रदान करने वाली एक केंद्रीकृत इकाई तक पहुंचने की आवश्यकता है। इसलिए सेवा ए और सेवा बी के बजाय कुछ संसाधन तक पहुंचना है ताकि पता लगाया जा सके कि ग्राहक एक्स के पास कुछ करने की अनुमति नहीं है या नहीं, सेवा ए और बी को एक्स से टोकन प्राप्त होता है जो उसकी / उसकी अनुमतियों को प्रमाणित करता है (आमतौर पर एक 3rd द्वारा जारी किया जाता है) पार्टी)। वैसे भी, JWT एक उपकरण है जो एक सिस्टम में सेवाओं के बीच साझा स्थिति से बचने में मदद करता है, खासकर जब वे एक से अधिक सेवा प्रदाता द्वारा नियंत्रित होते हैं।
लियोनोव

1
इसके अलावा से jwt.io/introduction If the JWT contains the necessary data, the need to query the database for certain operations may be reduced, though this may not always be the case.
giantas

43

मैं उपयोगकर्ता मॉडल पर jwt संस्करण संख्या का रिकॉर्ड रखूंगा। नए jwt टोकन इस के लिए अपना संस्करण निर्धारित करेंगे।

जब आप jwt को मान्य करते हैं, तो बस यह जांचें कि इसमें उपयोगकर्ताओं के वर्तमान jwt संस्करण के बराबर संस्करण संख्या है।

किसी भी समय आप पुराने jwts को अमान्य करना चाहते हैं, बस उपयोगकर्ताओं को jwt संस्करण संख्या को टक्कर दें।


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

13
संभवत: आप पहले से ही अपने टोकन में एक उपयोगकर्ता आईडी जमा कर रहे हैं, और फिर डेटाबेस को यह जांचने के लिए क्वेरी कर रहा है कि उपयोगकर्ता मौजूद है / एपीआई समापन बिंदु तक पहुंचने के लिए अधिकृत है। इसलिए आप उपयोगकर्ता पर jwt टोकन संस्करण संख्या की तुलना करके कोई अतिरिक्त db क्वेरी नहीं कर रहे हैं।
दफ्तमनक

5
मुझे निश्चित रूप से नहीं कहना चाहिए, क्योंकि कई स्थितियों में आप सत्यापन के साथ टोकन का उपयोग कर सकते हैं जो डेटाबेस को बिल्कुल नहीं छूते हैं। लेकिन मुझे लगता है कि इस मामले में इससे बचना मुश्किल है।
दफ्तमोन्क जूल

11
क्या होगा यदि उपयोगकर्ता कई उपकरणों से लॉग इन करता है? क्या उन सभी में एक टोकन का उपयोग किया जाना चाहिए या पिछले सभी को अमान्य करना चाहिए?
meeDamian

10
मैं @SergioCorrea से सहमत हूं, इससे JWT लगभग किसी भी अन्य टोकन प्रमाणीकरण तंत्र के रूप में स्टेटफुल हो जाएगा।
एड जे।

40

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

लक्ष्य:

  • डेटा स्टोर (राज्य-कम) का उपयोग कम करें।
  • सभी उपयोगकर्ताओं को लॉग आउट करने के लिए बाध्य करने की क्षमता।
  • किसी भी व्यक्ति को किसी भी समय लॉग आउट करने की क्षमता।
  • एक निश्चित समय के बाद पासवर्ड फिर से दर्ज करने की क्षमता।
  • कई ग्राहकों के साथ काम करने की क्षमता।
  • जब कोई उपयोगकर्ता किसी विशेष क्लाइंट से लॉगआउट पर क्लिक करता है, तो री-लॉग को बाध्य करने की क्षमता। (उपयोगकर्ता को दूर जाने के बाद ग्राहक टोकन को "किसी को हटाने" के लिए रोकना - अतिरिक्त जानकारी के लिए टिप्पणियां देखें)

समाधान:

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

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

विपक्ष:

  • फिर भी ताज़ा टोकन अनुरोध पर डेटा स्टोर लुकअप करना आवश्यक है।
  • टोकन के TTL तक पहुंचने के लिए अमान्य टोकन कार्य करना जारी रख सकते हैं।

पेशेवरों:

  • वांछित कार्यक्षमता प्रदान करता है।
  • सामान्य ऑपरेशन के तहत ताज़ा टोकन कार्रवाई उपयोगकर्ता से छिपाई गई है।
  • केवल हर अनुरोध के बजाय ताज़ा अनुरोधों पर डेटा स्टोर लुकअप करना आवश्यक है। यानी 1 प्रति सेकंड के बजाय हर 15 मिनट।
  • बहुत कम ब्लैकलिस्ट करने के लिए सर्वर साइड स्टेट को छोटा करता है।

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


उस परिदृश्य के बारे में जहां एक व्यक्ति एक कंप्यूटर से उठता है और दूसरे व्यक्ति को उसी कंप्यूटर का उपयोग करने देता है? 1 व्यक्ति लॉगआउट करेगा और उम्मीद करेगा कि लॉगआउट तुरंत दूसरे व्यक्ति को ब्लॉक कर देगा। यदि दूसरा व्यक्ति औसत उपयोगकर्ता है, तो ग्राहक टोकन को हटाकर उपयोगकर्ता को आसानी से रोक सकता है। लेकिन अगर दूसरे उपयोगकर्ता के पास हैकिंग कौशल है, तो उपयोगकर्ता के पास 1 उपयोगकर्ता के रूप में प्रमाणित करने के लिए अभी भी वैध टोकन को पुनर्प्राप्त करने का समय है। ऐसा लगता है कि बिना देरी के टोकन को तुरंत अमान्य करने की आवश्यकता से बचने का कोई तरीका नहीं है।
जो लैप

5
या आप अपने JWT को सेशन / लोकल स्टोरेज या कुकी से हटा सकते हैं।
कामिल Kiełczewski

1
धन्यवाद @Ashtonian व्यापक शोध करने के बाद, मैंने JWTs को छोड़ दिया। जब तक आप गुप्त कुंजी को सुरक्षित करने के लिए असाधारण लंबाई तक नहीं जाते हैं, या जब तक आप एक सुरक्षित OAuth कार्यान्वयन के लिए नहीं जाते हैं, तब तक JWTs नियमित सत्रों की तुलना में बहुत अधिक कमजोर होते हैं। मेरी पूरी रिपोर्ट देखें: by.jtl.xyz/2016/06/the-unspoken-vulnerability-of-jwts.html
जो लैप

2
रिफ्रेशिंग टोकन का उपयोग ब्लैक लिस्ट करने की अनुमति देने की कुंजी है। महान स्पष्टीकरण: auth0.com/blog/...
Rohmer

1
यह मुझे सबसे अच्छा जवाब लगता है क्योंकि यह एक लंबे समय से ताज़ा ताज़ा टोकन के साथ एक अल्पकालिक अभिगम टोकन को जोड़ता है जिसे ब्लैकलिस्ट किया जा सकता है। लॉगआउट पर, क्लाइंट को एक्सेस टोकन को हटा देना चाहिए ताकि दूसरा उपयोगकर्ता पहुंच प्राप्त न कर सके (भले ही एक्सेस टोकन लॉगआउट के बाद कुछ और मिनटों के लिए वैध रहेगा)। @ जो लैप का कहना है कि एक हैकर (दूसरा उपयोगकर्ता) डिलीट होने के बाद भी एक्सेस टोकन प्राप्त करता है। कैसे?
M3RS

14

एक दृष्टिकोण जिस पर मैं विचार कर रहा हूं, वह हमेशा iatJWT में एक (जारी) मूल्य है। फिर जब कोई उपयोगकर्ता लॉग आउट करता है, तो उस टाइमस्टैम्प को उपयोगकर्ता रिकॉर्ड पर संग्रहीत करें। JWT को मान्य करते समय बस iatअंतिम लॉग आउट टाइमस्टैम्प की तुलना करें । यदि iatयह पुराना है, तो यह मान्य नहीं है। हां, आपको डीबी में जाना होगा, लेकिन अगर जेडब्ल्यूटी अन्यथा मान्य है, तो मैं हमेशा उपयोगकर्ता रिकॉर्ड खींच रहा हूं।

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

यह भी एक प्रणाली में सभी JWTs को अमान्य करने के लिए एक अच्छा तंत्र हो सकता है। चेक का हिस्सा अंतिम वैध iatसमय के वैश्विक टाइमस्टैम्प के खिलाफ हो सकता है ।


1
अच्छा विचार! "एक डिवाइस" समस्या को हल करने के लिए यह एक लॉगआउट के बजाय एक आकस्मिक सुविधा बनाना है। उपयोगकर्ता रिकॉर्ड पर एक तारीख संग्रहीत करें जो इससे पहले जारी किए गए सभी टोकन को अमान्य करता है। जैसे कुछ token_valid_after, या कुछ। बहुत बढ़िया!
OneHoopyFrood

1
अरे @OneHoopyFrood आपके पास एक बेहतर उदाहरण में विचार को समझने में मेरी मदद करने के लिए एक उदाहरण कोड है? तुम्हारी मदद के लिए शुक्रिया!
अलेवेंटुराइयो

2
अन्य सभी प्रस्तावित समाधानों की तरह, यह एक डेटाबेस लुकअप की आवश्यकता है, यही कारण है कि यह प्रश्न मौजूद है क्योंकि उस लुकअप से बचना यहां सबसे महत्वपूर्ण बात है! (प्रदर्शन, मापनीयता)। सामान्य परिस्थितियों में आपको उपयोगकर्ता डेटा रखने के लिए DB लुकअप की आवश्यकता नहीं है, आपको पहले से ही क्लाइंट से मिल गया है।
रोब इवांस

9

मैं यहाँ थोड़ी देर से हूँ, लेकिन मुझे लगता है कि मेरे पास एक अच्छा समाधान है।

मेरे डेटाबेस में "last_password_change" कॉलम है जो उस समय और समय को संग्रहीत करता है जब पासवर्ड अंतिम बार बदला गया था। मैं JWT में जारी करने की तारीख / समय भी संग्रहीत करता हूं। एक टोकन को मान्य करते समय, मैं जांचता हूं कि क्या टोकन जारी किए जाने के बाद पासवर्ड बदल दिया गया है और यदि यह टोकन अस्वीकृत हो गया है, भले ही यह अभी तक समाप्त नहीं हुआ है।


1
आप टोकन को कैसे अस्वीकार करते हैं? क्या आप एक संक्षिप्त उदाहरण कोड दिखा सकते हैं?
अलेक्सवेंटुरायो

1
if (jwt.issue_date < user.last_pw_change) { /* not valid, redirect to login */}
वानुअन

15
एक db देखने की आवश्यकता है!
रोब इवांस

5

आपके पास आपके उपयोगकर्ता के दस्तावेज़ / रिकॉर्ड पर आपके DB पर "last_key_used" फ़ील्ड हो सकता है।

जब उपयोगकर्ता उपयोगकर्ता के साथ लॉग इन करता है और पास होता है, तो एक नया यादृच्छिक स्ट्रिंग उत्पन्न करता है, इसे last_key_used फ़ील्ड में संग्रहीत करता है, और टोकन साइन करते समय इसे पेलोड में जोड़ता है।

जब उपयोगकर्ता टोकन का उपयोग करने में लॉग इन करता है, तो DB में अंतिम_की_ का उपयोग करके चेक करें ताकि टोकन में से मेल खा सके।

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


यह वह उपाय है जिस पर मैं विचार कर रहा हूं, लेकिन इसमें ये कमियां हैं: (1) आप या तो डीबी-लुकअप कर रहे हैं, प्रत्येक अनुरोध पर रैंडम चेक करने के लिए (सत्रों के बजाय टोकन का उपयोग करने का कारण बताकर) या आप कर रहे हैं केवल एक ताज़ा टोकन समाप्त होने के बाद रुक-रुक कर जाँच करना (उपयोगकर्ताओं को तुरंत लॉग आउट करने से रोकना या सत्रों को तुरंत समाप्त किया जाना); और (2) लॉग आउट करने से उपयोगकर्ता सभी ब्राउज़रों और सभी उपकरणों से बाहर हो जाता है (जो परंपरागत रूप से अपेक्षित व्यवहार नहीं है)।
जो लैप

उपयोगकर्ता द्वारा लॉग आउट करने पर आपको कुंजी को बदलने की आवश्यकता नहीं है, केवल जब वे अपना पासवर्ड बदलते हैं या-यदि आप इसे प्रदान करते हैं- जब वे सभी उपकरणों से लॉग आउट करना चुनते हैं
NickVarcha

3

इस तरह एक इन-मेमोरी सूची रखें

user_id   revoke_tokens_issued_before
-------------------------------------
123       2018-07-02T15:55:33
567       2018-07-01T12:34:21

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


2
अधिकांश उत्पादन साइटें एक से अधिक सर्वरों पर चलती हैं इसलिए यह समाधान काम नहीं करेगा। Redis या इसी तरह के अन्य इंटरकॉपीस कैश को जोड़ने से सिस्टम को जटिल बनाता है और अक्सर समाधान की तुलना में अधिक समस्याएं लाता है।
user2555515

@ user2555515 सभी सर्वरों को डेटाबेस के साथ सिंक्रनाइज़ किया जा सकता है। यह आपकी पसंद है डेटाबेस को हर बार मारना या नहीं। आप बता सकते हैं कि यह क्या समस्याएं लाता है।
एडुआर्डो

3

------------------------ इस उत्तर के लिए थोड़ी देर हो सकती है लेकिन हो सकता है कि यह किसी की मदद करे ------------- -----------

क्लाइंट साइड से , ब्राउज़र के भंडारण से टोकन को हटाने का सबसे आसान तरीका है।

लेकिन, अगर आप नोड सर्वर पर टोकन को नष्ट करना चाहते हैं -

JWT पैकेज के साथ समस्या यह है कि यह टोकन को नष्ट करने के लिए कोई विधि या तरीका प्रदान नहीं करता है। आप JWT के संबंध में विभिन्न विधियों का उपयोग कर सकते हैं जो ऊपर उल्लिखित हैं। लेकिन यहाँ मैं jwt-redis के साथ जाता हूँ।

तो सर्वर पर टोकन को नष्ट करने के लिए आप JWT के बजाय jwt-redis पैकेज का उपयोग कर सकते हैं

यह लाइब्रेरी (jwt-redis) पूरी तरह से लाइब्रेरी jsonwebtoken की पूरी कार्यक्षमता को दोहराती है, जिसमें एक महत्वपूर्ण जोड़ है। Jwt-redis आपको वैधता सत्यापित करने के लिए रेडिस में टोकन लेबल को स्टोर करने की अनुमति देता है। रेडिस में एक टोकन लेबल की अनुपस्थिति टोकन को मान्य नहीं बनाती है। Jwt-redis में टोकन को नष्ट करने के लिए, एक नष्ट विधि है

यह इस तरह से काम करता है:

1) nwt से jwt-redis स्थापित करें

2) बनाने के लिए -

var redis = require('redis');
var JWTR =  require('jwt-redis').default;
var redisClient = redis.createClient();
var jwtr = new JWTR(redisClient);

jwtr.sign(payload, secret)
    .then((token)=>{
            // your code
    })
    .catch((error)=>{
            // error handling
    });

3) सत्यापित करने के लिए -

jwtr.verify(token, secret);

4) नष्ट करने के लिए -

jwtr.destroy(token)

नोट : आप expiresIn टोकन के साइनइन के दौरान उसी तरह प्रदान कर सकते हैं जैसे कि JWT में प्रदान किया गया है।

हो सकता है यह किसी को मदद करेगा


2

क्यों न केवल ji क्लेम (nonce) का उपयोग किया जाए और उस सूची में उपयोगकर्ता रिकॉर्ड फ़ील्ड (db निर्भर) के रूप में संग्रहीत करें, लेकिन बहुत कम से कम अल्पविराम से अलग की गई सूची ठीक है)? अलग-अलग लुकअप की कोई आवश्यकता नहीं है, क्योंकि अन्य लोगों ने बताया है कि आप वैसे भी उपयोगकर्ता रिकॉर्ड प्राप्त करना चाहते हैं, और इस तरह से आपके पास अलग-अलग क्लाइंट इंस्टेंसेस के लिए कई वैध टोकन हो सकते हैं ("हर जगह लॉगआउट करें" सूची को खाली करने के लिए रीसेट कर सकते हैं)


हां यह। हो सकता है कि उपयोगकर्ता तालिका और नई (सत्र) तालिका के बीच एक-से-कई संबंध बनाएं, इसलिए आप जेटीआई दावों के साथ मेटा डेटा स्टोर कर सकते हैं।
पीटर लाडा

2
  1. टोकन के लिए 1 दिन का समय दें
  2. एक दैनिक ब्लैकलिस्ट बनाए रखें।
  3. अमान्य / लॉगआउट टोकन को ब्लैकलिस्ट में डालें

टोकन सत्यापन के लिए, टोकन समाप्ति समय के लिए पहले जांच करें और फिर टोकन समाप्त नहीं होने पर ब्लैकलिस्ट करें।

लंबे सत्र की जरूरतों के लिए, टोकन समाप्ति समय बढ़ाने के लिए एक तंत्र होना चाहिए।


4
टोकन को ब्लैक लिस्ट में डाल दें और आपकी स्टेटलेसनेस हो जाती है
केरम बेयोडन

2

पार्टी के लिए देर से, कुछ शोध के बाद मेरे दो सेंट नीचे दिए गए हैं। लॉगआउट के दौरान, सुनिश्चित करें कि निम्नलिखित चीजें हो रही हैं ...

क्लाइंट संग्रहण / सत्र को साफ़ करें

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

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


2

अद्वितीय प्रति उपयोगकर्ता स्ट्रिंग, और वैश्विक स्ट्रिंग एक साथ हैशेड

JWT गुप्त भाग के रूप में सेवा करने के लिए दोनों व्यक्तिगत और वैश्विक टोकन अमान्यकरण की अनुमति देते हैं। डीबी लुकअप की कीमत पर अधिकतम लचीलापन / अनुरोध के दौरान पढ़ें। साथ ही कैश करना आसान है, क्योंकि वे शायद ही कभी बदलते हैं।

यहाँ एक उदाहरण है:

HEADER:ALGORITHM & TOKEN TYPE

{
  "alg": "HS256",
  "typ": "JWT"
}
PAYLOAD:DATA

{
  "sub": "1234567890",
  "some": "data",
  "iat": 1516239022
}
VERIFY SIGNATURE

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload), 
  HMACSHA256('perUserString'+'globalString')
)

where HMACSHA256 is your local crypto sha256
  nodejs 
    import sha256 from 'crypto-js/sha256';
    sha256(message);

उदाहरण के उपयोग के लिए https://jwt.io देखें (सुनिश्चित नहीं कि वे गतिशील 256 बिट रहस्यों को संभालते हैं)


1
कुछ और विस्तार पर्याप्त होगा
विशालकाय

2
@giantas, मुझे लगता है कि मार्क का मतलब हस्ताक्षर वाला हिस्सा है। इसलिए JWT पर हस्ताक्षर करने के लिए केवल एक कुंजी का उपयोग करने के बजाय, इसे एक कुंजी को संयोजित करें जो प्रत्येक क्लाइंट के लिए अद्वितीय हो। इसलिए, यदि आप किसी उपयोगकर्ता के सभी सत्र को अमान्य करना चाहते हैं, तो बस उस उपयोगकर्ता के लिए कुंजी बदल दें और यदि आप अपने सिस्टम के सभी सत्र को अमान्य कर दें, तो बस उस वैश्विक एकल कुंजी को बदल दें।
टॉमी आर्या प्रादा

1

मैंने इसे निम्न तरीके से किया:

  1. एक जनरेट करें unique hash, और फिर इसे रेडिस और अपने JWT में स्टोर करें । इसे सत्र कहा जा सकता है
    • हम विशेष रूप से JWT द्वारा किए गए अनुरोधों की संख्या को भी संग्रहीत करेंगे - हर बार जब एक jwt सर्वर को भेजा जाता है, तो हम अनुरोधों को पूर्णांक बढ़ाते हैं । (यह वैकल्पिक है)

इसलिए जब कोई उपयोगकर्ता लॉग इन करता है, तो एक अद्वितीय हैश बनाया जाता है, जिसे रेडिस में संग्रहीत किया जाता है और आपके JWT में इंजेक्ट किया जाता है ।

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

हम इससे विस्तार कर सकते हैं और अपने JWT को और अधिक सुरक्षित बना सकते हैं, यहाँ बताया गया है:

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

इसका मतलब यह है कि JWT लगातार बदल रहा है और बासी JWT के हैक होने, चोरी होने या कुछ और होने से रोकता है।


1
आप स्वयं टोकन को हैश कर सकते हैं और उस मूल्य को लालियों में संग्रहीत कर सकते हैं, बल्कि एक नए हैश को टोकन में इंजेक्ट कर सकते हैं।
फ्राग

जेडब्ल्यूटी में भी जांच audऔर jtiदावे करें, आप सही रास्ते पर हैं।
पीटर लाडा

1

यदि आप उपयोगकर्ता टोकन को रद्द करने में सक्षम होना चाहते हैं, तो आप अपने DB पर सभी जारी टोकन का ट्रैक रख सकते हैं और जांच सकते हैं कि क्या वे सत्र-जैसी तालिका में मान्य (मौजूद) हैं। नकारात्मक पक्ष यह है कि आप हर अनुरोध पर डीबी को मारेंगे।

मैंने इसे आजमाया नहीं है, लेकिन मैं डीबी हिट को न्यूनतम रखते हुए टोकन निरस्तीकरण की अनुमति देने के लिए निम्न विधि सुझाता हूं -

डेटाबेस चेक दर को कम करने के लिए, सभी निर्धारक संघ के अनुसार सभी जारी किए गए JWT टोकन को एक्स समूहों में विभाजित करें (जैसे, उपयोगकर्ता आईडी के पहले अंक द्वारा 10 समूह)।

प्रत्येक JWT टोकन समूह आईडी और टोकन निर्माण पर बनाई गई टाइमस्टैम्प धारण करेगा। जैसे,{ "group_id": 1, "timestamp": 1551861473716 }

सर्वर सभी समूह आईडी को स्मृति में रखेगा और प्रत्येक समूह में एक टाइमस्टैम्प होगा जो इंगित करता है कि उस समूह से संबंधित उपयोगकर्ता का अंतिम लॉग-आउट इवेंट कब था। जैसे,{ "group1": 1551861473714, "group2": 1551861487293, ... }

JWT टोकन के साथ अनुरोध जिसमें पुराने समूह टाइमस्टैम्प हैं, की वैधता (DB हिट) के लिए जाँच की जाएगी और यदि मान्य है, तो एक नए टाइमस्टैम्प के साथ एक नया JWT टोकन क्लाइंट के भविष्य के उपयोग के लिए जारी किया जाएगा। यदि टोकन का समूह टाइमस्टैम्प नया है, तो हमें JWT (नो DB हिट) पर भरोसा है।

इसलिए -

  1. हम केवल एक JWT टोकन को DB का उपयोग करके मान्य करते हैं यदि टोकन में एक पुराना समूह टाइमस्टैम्प है, जबकि भविष्य के अनुरोधों को तब तक मान्य नहीं किया जाएगा जब तक उपयोगकर्ता के समूह में कोई लॉग-आउट नहीं करेगा।
  2. हम टाइमस्टैम्प परिवर्तनों की संख्या को सीमित करने के लिए समूहों का उपयोग करते हैं (कहते हैं कि कोई उपयोगकर्ता लॉग-इन कर रहा है और जैसे कल नहीं है - केवल सभी के बजाय सीमित संख्या में उपयोगकर्ताओं को प्रभावित करेगा)
  3. हम मेमोरी में आयोजित टाइमस्टैम्प की मात्रा को सीमित करने के लिए समूहों की संख्या को सीमित करते हैं
  4. टोकन को अमान्य करना एक हवा है - बस इसे सत्र तालिका से हटा दें और उपयोगकर्ता के समूह के लिए एक नया टाइमस्टैम्प उत्पन्न करें।

समान सूची को मेमोरी में रखा जा सकता है (c # के लिए आवेदन) और यह प्रत्येक अनुरोध के लिए db को हिट करने की आवश्यकता को समाप्त कर देगा। सूची को आवेदन शुरू होने पर db से लोड किया जा सकता है
dvdmn

1

यदि "सभी उपकरणों से लॉगआउट" विकल्प स्वीकार्य है (ज्यादातर मामलों में यह है):

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

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


0

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

  1. LastValidTime (डिफ़ॉल्ट: निर्माण समय)
  2. लॉग-इन (डिफ़ॉल्ट: सत्य)

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

जब हम JWT बनाते हैं तो हमारे पास पेलोड में JWT का निर्माण समय होगा। जब हम एक सेवा के लिए अधिकृत करते हैं तो हम 3 शर्तों की जांच करेंगे

  1. क्या JWT वैध है
  2. क्या JWT पेलोड निर्माण का समय उपयोगकर्ता LastValidTime से अधिक है
  3. क्या उपयोगकर्ता लॉग-इन है

चलो एक व्यावहारिक परिदृश्य देखते हैं।

उपयोगकर्ता एक्स में दो डिवाइस ए, बी हैं। उसने डिवाइस ए और डिवाइस बी का उपयोग करके शाम 7 बजे हमारे सर्वर में लॉग इन किया (बता दें कि जेडब्ल्यूटी की समय सीमा 12 घंटे है)। A और B दोनों के पास JWT के साथ क्रिएटटाइम: 7pm है

रात 9 बजे उसने अपना डिवाइस बी खो दिया। वह तुरंत डिवाइस ए से लॉग आउट हो गया। इसका मतलब है कि अब हमारे डेटाबेस एक्स उपयोगकर्ता प्रविष्टि में लास्टवैलिडाइम "थैडेट: 9: 00: xx: xxx" और लॉग-इन के रूप में "झूठा" है।

9:30 बजे श्रीमान डिवाइस बी का उपयोग करके लॉग इन करने का प्रयास करते हैं। हम डेटाबेस की जाँच करेंगे यहां तक ​​कि लॉग-इन भी गलत है इसलिए हम अनुमति नहीं देंगे।

10 बजे मि। एक्स अपने डिवाइस ए से लॉग इन करता है। अब डिवाइस ए में जेडडब्ल्यूटी बना हुआ समय है: 10 बजे। अब डेटाबेस लॉग-इन "सही" पर सेट है

10:30 बजे श्रीमान लॉग इन करने की कोशिश करते हैं। भले ही लॉग-इन सही है। LastValidTime डेटाबेस में 9 बजे है, लेकिन B के JWT ने 7pm के रूप में समय बनाया है। इसलिए उसे सेवा तक पहुंचने की अनुमति नहीं है। तो डिवाइस बी का उपयोग किए बिना पासवर्ड वह एक डिवाइस लॉग आउट के बाद पहले से ही निर्मित जेडब्ल्यूटी का उपयोग नहीं कर सकता है।


0

आईएएमए समाधान जैसे कि क्लोकॉक (जो आईशैव ने काम किया है) जैसे टोकन निरस्तीकरण समापन बिंदु प्रदान करता है

टोकन निरसन समापन बिंदु /realms/{realm-name}/protocol/openid-connect/revoke

यदि आप केवल एक उपयोगकर्ता (या उपयोगकर्ता) को लॉगआउट करना चाहते हैं, तो आप एक समापन बिंदु भी कह सकते हैं (यह केवल टोकन अमान्य होगा)। फिर से, कीक्लोक के मामले में, रोलींग पार्टी को केवल समापन बिंदु को कॉल करने की आवश्यकता है

/realms/{realm-name}/protocol/openid-connect/logout

यदि आप और अधिक सीखना चाहते हैं तो लिंक करें


-1

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

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

एक ब्लैक-लिस्ट के विकल्प, उसी समाधान का उपयोग करके, आप इसे प्रति सत्र में रेडिस में सहेजे गए हैश के साथ कर सकते हैं क्योंकि यह अन्य उत्तर बताता है (हालांकि यह सुनिश्चित नहीं है कि कई उपयोगकर्ताओं के साथ अधिक कुशल होगा)।

क्या यह भयानक रूप से ध्वनि करता है? यह मेरे लिए करता है!

डिस्क्लेमर: मैंने रेडिस का इस्तेमाल नहीं किया है।


-1

यदि आप axios या इसी तरह के वादे पर आधारित http अनुरोध का उपयोग कर रहे हैं, तो आप बस .then()भाग के अंदर के छोर पर टोकन को नष्ट कर सकते हैं । उपयोगकर्ता द्वारा इस फ़ंक्शन को निष्पादित करने के बाद इसे प्रतिक्रिया (.then) भाग में लॉन्च किया जाएगा (सर्वर एंडपॉइंट से परिणाम कोड ठीक होना चाहिए, 200)। डेटा की खोज के दौरान उपयोगकर्ता इस मार्ग पर क्लिक करने के बाद, यदि डेटाबेस फ़ील्ड user_enabledझूठी है , तो यह टोकन को नष्ट कर देगा और उपयोगकर्ता तुरंत लॉग-ऑफ हो जाएगा और संरक्षित मार्गों / पृष्ठों तक पहुंचने से रोक दिया जाएगा। उपयोगकर्ता को स्थायी रूप से लॉग ऑन करने के दौरान हमें टोकन समाप्त होने का इंतजार नहीं करना होगा।

function searchForData() {   // front-end js function, user searches for the data
    // protected route, token that is sent along http request for verification
    var validToken = 'Bearer ' + whereYouStoredToken; // token stored in the browser 

    // route will trigger destroying token when user clicks and executes this func
    axios.post('/my-data', {headers: {'Authorization': validToken}})
     .then((response) => {
   // If Admin set user_enabled in the db as false, we destroy token in the browser localStorage
       if (response.data.user_enabled === false) {  // user_enabled is field in the db
           window.localStorage.clear();  // we destroy token and other credentials
       }  
    });
     .catch((e) => {
       console.log(e);
    });
}

-3

मैं केवल उपयोगकर्ता तालिका में टोकन सहेजता हूं, जब उपयोगकर्ता लॉगिन मैं नया टोकन अपडेट करूंगा, और जब उपयोगकर्ता वर्तमान jwt के बराबर होगा।

मुझे लगता है कि यह सबसे अच्छा समाधान नहीं है लेकिन यह मेरे लिए काम करता है।


2
बेशक यह सबसे अच्छा नहीं है! डीबी तक पहुंच रखने वाला कोई भी व्यक्ति आसानी से किसी भी उपयोगकर्ता को लगा सकता है।
user2555515

1
@ user2555515 यह समाधान ठीक काम करता है यदि डेटाबेस पर संग्रहीत टोकन एन्क्रिप्ट किया गया है, जैसे डेटाबेस पर संग्रहीत कोई भी पासवर्ड होना चाहिए। ( Stateless JWTऔर Stateful JWTजो सत्रों के समान है) के बीच अंतर है। Stateful JWTएक टोकन श्वेतसूची को बनाए रखने से लाभ हो सकता है।
TheDarkIn1978
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.