यदि एक वेब एप्लिकेशन में उपयोगकर्ता शामिल हैं, तो हमेशा की तरह, उनके डेटा को संरक्षित और सुरक्षित किया जाना चाहिए।
वेब एप्लिकेशन को सुरक्षित करना कई चीजें हो सकती हैं। इस पोस्ट में, हम वेब सुरक्षा के एक उपसमुच्चय पर चर्चा करेंगे जिसमें JSON वेब टोकन (JWTs) और रूबी ऑन रेल्स वेब एप्लिकेशन फ्रेमवर्क का उपयोग करके प्रमाणीकरण शामिल है।
शुरू करते हैं!
JSON वेब टोकन क्या है?
एक JSON वेब टोकन इंटरनेट इंजीनियरिंग टास्क फोर्स (IETF) द्वारा परिभाषित एक इंटरनेट मानक है: "दो पक्षों के बीच स्थानांतरित किए जाने वाले दावों का प्रतिनिधित्व करने का एक कॉम्पैक्ट, URL-सुरक्षित साधन"।
यहां, "दावे" एक विषय के बारे में विविध जानकारी के टुकड़ों को संदर्भित करते हैं। एक दावे को नाम/मान जोड़ी के रूप में दर्शाया जाता है जहां नाम हमेशा एक स्ट्रिंग होता है, और मान कोई भी JSON मान हो सकता है।
JSON वेब टोकन की मूल संरचना
JWTs की जटिलताओं में तल्लीन करना इस पोस्ट के दायरे से बाहर है। उस ने कहा, JWTs की संरचना जानना उचित है।
एक JWT में तीन भाग होते हैं, जो एक अवधि द्वारा अलग किए जाते हैं: हेडर, पेलोड, और हस्ताक्षर।
एक उदाहरण JWT निम्नलिखित जैसा दिख सकता है:
पठनीयता के लिए, टोकन का प्रत्येक भाग एक नई लाइन पर शुरू होता है। व्यवहार में, भाग जुड़े हुए हैं।
यह टोकन एक सर्वर से क्लाइंट को भेजा जाता है। क्लाइंट खुद की पहचान करने और अनुरोध संसाधित करवाने के लिए टोकन को सर्वर को भेजता है।
पहला भाग, हेडर, टोकन उत्पन्न करने के लिए उपयोग किए गए एल्गोरिदम और टोकन के प्रकार के बारे में जानकारी रखता है। यदि डिकोड किया जाता है, तो हमें ऐसा कुछ मिलता है:
दूसरा भाग, पेलोड, उपयोगकर्ता के बारे में दावों का एक सेट रखता है। ज्यादातर मामलों में, यह क्लाइंट-सर्वर सेटअप में क्लाइंट होगा, और यह ऐसा दिख सकता है:
हस्ताक्षर (एक हस्ताक्षरित JWT का अंतिम भाग) टोकन को मान्य करता है। यह हेडर और पेलोड को Base64url एन्कोडिंग — RFC 4648 का उपयोग करके एन्कोड करके और फिर उन्हें एक अवधि विभाजक के साथ जोड़कर उत्पन्न होता है।
अनिवार्य रूप से, हस्ताक्षर बिट के साथ जो होता है वह यह है:
HMAC_SHA256 SHA-256 हैश फ़ंक्शन से निर्मित एक प्रकार का कुंजीकृत हैश एल्गोरिदम है जो हस्ताक्षर को हैश करता है। क्रिप्टोग्राफिक एल्गोरिदम की पसंद हेडर में "alg": "HS256" से आती है। यदि टोकन अनसाइन्ड है, तो इसमें हस्ताक्षर के बिना केवल हेडर और पेलोड होंगे।
आपके रूबी ऐप के लिए JWTs बनाम अन्य प्रमाणीकरण विधियाँ
JSON वेब टोकन, जैसा कि नाम से पता चलता है, टोकन-आधारित हैं। दूसरे छोर पर, हमारे पास सत्र-आधारित प्रमाणीकरण है: उपयोगकर्ताओं को प्रमाणित करने का एक अधिक पारंपरिक तरीका। सत्र-आधारित प्रमाणीकरण का प्रवाह टोकन-आधारित प्रमाणीकरण से काफी अलग है।
सत्र-आधारित प्रमाणीकरण का प्रवाह निम्नलिखित जैसा दिख सकता है:
- एक उपयोगकर्ता या क्लाइंट एक अनुरोध भेजता है जिसमें उपयोगकर्ता क्रेडेंशियल्स होते हैं।
- सर्वर उपयोगकर्ता को प्रमाणित करता है, एक सत्र संग्रहीत करता है, और एक सत्र आईडी लौटाता है जिसे ब्राउज़र में कुकी के रूप में संग्रहीत किया जाता है।
- क्लाइंट अपने बाद के अनुरोधों के साथ सर्वर को कुकीज़ भेजता है।
- सर्वर प्रस्तुत सत्र जानकारी का निरीक्षण करता है और, यदि मान्य है, तो उपयोगकर्ता को प्रमाणित करता है और क्लाइंट को अनुरोधित जानकारी लौटाता है।
जबकि सत्र-आधारित प्रमाणीकरण ज्यादातर क्लाइंट-सर्वर कनेक्शन के लिए उपयोग किया जाता है, टोकन-आधारित प्रमाणीकरण अक्सर सर्वर-सर्वर कनेक्शन (उदाहरण के लिए, दो API के बीच) के साथ उपयोग किया जाता है।
एक महत्वपूर्ण अंतर यह नोट करना है कि सत्र-आधारित प्रमाणीकरण के साथ, प्रमाणीकरण स्थिति सर्वर पर संभाली जाती है — जबकि टोकन क्लाइंट पर प्रबंधित होते हैं।
प्रमाणीकरण के लिए JWTs का उपयोग क्यों करें?
अपेक्षाकृत सरल रूप से लागू होने के अलावा, प्रमाणीकरण के लिए JSON वेब टोकन का उपयोग करने के कुछ अन्य फायदे हैं, जैसे:
- वे स्टेटलेस हैं, जिसका अर्थ है कि सत्र स्टोर आवश्यक नहीं है। टोकन में स्वयं सभी उपयोगकर्ता जानकारी होती है, इसलिए प्रत्येक अनुरोध पर जानकारी के लिए डेटाबेस या प्रमाणीकरण सर्वर को क्वेरी करने की कोई आवश्यकता नहीं है।
- JWTs आम तौर पर अधिक प्रदर्शनकारी हैं पारंपरिक प्रमाणीकरण विधियों की तुलना में (जब तक सर्वर किसी उपयोगकर्ता को प्रमाणित करने के लिए डेटाबेस या स्टोर के खिलाफ कोई लुकअप नहीं करता), जो उन्हें काफी कुशल बनाता है।
- वे ठोस सुरक्षा गारंटी भी प्रदान करते हैं, जिसमें हस्ताक्षरित JWTs सुरक्षा उपाय प्रदान करते हैं ताकि कोई हमलावर या क्लाइंट संरक्षित डेटा तक पहुंच प्राप्त करने के लिए टोकन को संशोधित न कर सके।
रूबी ऐप्स के लिए JWT सर्वोत्तम अभ्यास
यह कहे बिना जाता है कि JWTs पर हस्ताक्षर करने के लिए उपयोग की जाने वाली गुप्त कुंजियाँ लंबी, यादृच्छिक, और जटिल वर्ण संयोजन होनी चाहिए। यह सुनिश्चित करता है कि कुंजियाँ पर्याप्त रूप से सुरक्षित हैं और हमलावरों के लिए उन्हें ब्रूट-फोर्स करना कठिन है।
रेल्स द्वारा उत्पन्न गुप्त कुंजियाँ अधिकांश भाग के लिए सुरक्षित हैं, लेकिन यदि आप गलती से कुंजियाँ कमिट करते हैं और उन्हें प्रकट करते हैं तो सुरक्षा गारंटी शून्य हो जाती है।
नेटवर्क पर पार्टियों के बीच टोकन परिवहन करते समय ट्रांसपोर्ट लेयर सिक्योरिटी (TLS) का उपयोग करना भी महत्वपूर्ण है। TLS मैन-इन-द-मिडल अटैक को कम कर सकता है (टोकन और सत्र-आधारित दोनों प्रमाणीकरण विधियाँ ऐसे हमलों की चपेट में हैं)।
रेल्स ऐप में JWT प्रमाणीकरण लागू करना
आइए टोकन-आधारित प्रमाणीकरण प्रवाह पर एक नज़र डालें:

सत्र-आधारित प्रमाणीकरण के विपरीत, एक स्टेटफुल प्रमाणीकरण तकनीक जहां हम प्रमाणित उपयोगकर्ता को ट्रैक करने के लिए सत्र का उपयोग करते हैं, JWTs के साथ टोकन-आधारित प्रमाणीकरण स्टेटलेस है; सर्वर पर उपयोगकर्ता की प्रमाणीकरण स्थिति के बारे में कोई भी जानकारी संग्रहीत करने की कोई आवश्यकता नहीं है। यह एप्लिकेशन डिज़ाइन को सरल बनाता है।
इस पोस्ट में, हम मान लेंगे कि हमारा एप्लिकेशन फ्रंटएंड और बैकएंड में विभाजित है। प्रमाणीकरण बैकएंड पर होता है, इसलिए हम प्रमाणीकरण के साथ एक रेल्स API बैकएंड बना रहे होंगे।
इस पोस्ट में नमूना कोड रेल्स 7.0.5 और रूबी 3.2.2 पर आधारित है।
jwt और bcrypt रूबी जेम्स का उपयोग करना
हमें अपने एप्लिकेशन के लिए दो जेम्स की आवश्यकता होगी: jwt और bcrypt।
jwt RFC 7519 OAuth JSON वेब टोकन मानक का एक रूबी कार्यान्वयन है। bcrypt OpenBSD bcrypt() पासवर्ड हैशिंग एल्गोरिदम के लिए एक रूबी बाइंडिंग है।
आप इस कोड रेपो में नमूना कोड के साथ अनुसरण कर सकते हैं।
नोट: jwt JWTs के साथ काम करने का एकमात्र समाधान नहीं है; एक और प्रसिद्ध जेम devise-jwt है, जो Devise और रेल्स के लिए JWT प्रमाणीकरण प्रदान करता है। लेकिन हम इस पोस्ट में jwt पर ध्यान केंद्रित करेंगे।
शुरू करते हैं।
हमारा रेल्स API बनाना
हमें सबसे पहले एक API एप्लिकेशन की आवश्यकता है। हम इसे इसके साथ बनाएंगे:
--api विकल्प यहां केवल API एप्लिकेशन के लिए रेल्स के एक छोटे स्टैक को पूर्व-कॉन्फ़िगर करता है।
Gemfile के अंदर, हम अपनी पहली निर्भरता, jwt जोड़ सकते हैं। हमारा दूसरा जेम, bcrypt, नव-निर्मित रेल्स एप्लिकेशन के Gemfile में पहले से ही है — हमें बस इसे अनकमेंट करना होगा।
हमें डेटाबेस में उपयोगकर्ता पासवर्ड को सुरक्षित रूप से हैश करने के लिए bcrypt की आवश्यकता है। यह नोट करना महत्वपूर्ण है कि हम bcrypt का सीधे उपयोग नहीं करेंगे। हम Active Model के has_secure_password क्लास मेथड का लाभ उठाएंगे, जो bcrypt पर निर्भर करता है।
एक नए रेल्स एप्लिकेशन के साथ आने वाले डिफ़ॉल्ट जेम्स को नज़रअंदाज करते हुए, हमारा Gemfile कुछ इस तरह दिखना चाहिए:
अब bundle install के साथ हमारे जेम्स इंस्टॉल करने का अच्छा समय है।
User और Product मॉडल जेनरेट करें
इसके बाद, हम दो मॉडल जेनरेट करेंगे: User और Product। User उपयोगकर्ताओं का प्रतिनिधित्व करने वाला मॉडल होगा और हम इसे उत्पादों तक पहुंच की अनुमति देने के लिए प्रमाणित करेंगे, जिन्हें Product मॉडल द्वारा दर्शाया गया है।
rails db:migrate के साथ हमारे माइग्रेशन चलाने के बाद, मॉडल के साथ हमारा सेटअप पूरा हो गया है, और हमारा स्कीमा, db/schema.rb में पाया जाता है, अब इस तरह दिखना चाहिए:
इस स्तर पर यह इंगित करना महत्वपूर्ण है कि हम संभावित मुद्दों जैसे डेटाबेस बाधाओं, मान्यताओं, विशिष्टता सुनिश्चित करने, आदि को जानबूझकर नज़रअंदाज कर रहे हैं। इस पोस्ट के लिए, हम त्रुटियों को संभालने, दूसरों के बीच में उपेक्षा करेंगे। हमारा उद्देश्य यहां हमारे रूबी एप्लिकेशन को सुरक्षित करने के लिए स्टेटलेस प्रमाणीकरण के रूप में JWTs को कार्रवाई में प्रदर्शित करना है। एक उत्पादन एप्लिकेशन में, आप यह सुनिश्चित करना चाहेंगे कि ये सभी कवर किए गए हैं।
jwt जेम रैपर बनाएं
अगला कदम हमारे द्वारा पहले इंस्टॉल किए गए jwt जेम के चारों ओर एक रैपर बनाना है। हम इस रैपर का उपयोग सर्वर से क्लाइंट तक दावों को एन्कोड और डिकोड करने के लिए करेंगे। इसके लिए, हम एक app/lib फोल्डर बनाएंगे।
हम रेल्स के साथ आने वाले lib फोल्डर का उपयोग नहीं कर रहे हैं क्योंकि यह ऑटोलोडेड नहीं है। app के तहत सब कुछ डिफ़ॉल्ट रूप से ऑटोलोडेड और ईगर-लोडेड है, जो हमारे मामले में एक सरल सेटअप के लिए बनाता है।
हमारी रैपर क्लास app/lib/json_web_token.rb में पाई जाती है और इस तरह दिखती है:
यहां मुख्य विधियाँ encode — उपयोगकर्ता जानकारी को एन्कोड करने के लिए — और decode — बाद में सर्वर में उपयोगकर्ता जानकारी को डिकोड करने के लिए हैं। ध्यान दें कि हम JWT.encode और JWT.decode के माध्यम से jwt जेम को एन्कोडिंग और डिकोडिंग कार्यों को कैसे सौंप रहे हैं।
इस बिंदु पर, आप पहले से ही अपने रेल्स कंसोल में इस क्लास का परीक्षण कर सकते हैं:
ध्यान दें कि JsonWebToken.encode(data) का परिणाम एक अवधि द्वारा तीन भागों में विभाजित है, जो हेडर, पेलोड, और हस्ताक्षर उत्पन्न करता है। हमारे पास हस्ताक्षर बिट है क्योंकि हमने अपने पेलोड पर हस्ताक्षर किए हैं एक गुप्त कुंजी के साथ जो रेल्स Rails.application.secrets.secret_key_base के माध्यम से प्रदान करता है।
वापस User मॉडल पर
अब app/models/user.rb पर हमारे User मॉडल पर जाने का अच्छा समय होगा। हमें बस यहां has_secure_password क्लास मेथड जोड़ने की आवश्यकता है:
has_secure_password हमारे उपयोगकर्ताओं के पासवर्ड को डेटाबेस में सुरक्षित रूप से हैश करता है।
रेल्स में एक नमूना उपयोगकर्ता और उत्पाद बनाएं
अब हम अपने डेटाबेस में एक नमूना उपयोगकर्ता और उत्पाद उत्पन्न करने और हमारे एप्लिकेशन की सुरक्षा का परीक्षण करने के लिए रेल्स कंसोल में जा सकते हैं:
आप अपने seeds.rb फ़ाइल में कोड का वही टुकड़ा रख सकते हैं यदि आप अपना डेटाबेस रीसेट करते हैं तो कुछ टाइपिंग बचाने के लिए।
रेल्स कंट्रोलर में JWTs का उपयोग करना
अगले चरणों में, हम अपने कंट्रोलर के अंदर JWTs का उपयोग करके सुरक्षा लागू करेंगे। शुरू करने के लिए एक अच्छी जगह app/controllers/application_controller.rb पर ApplicationController है:
यहां, हम एक authenticate विधि बनाते हैं जो उपयोगकर्ताओं द्वारा हमें भेजे गए JSON वेब टोकन को डिकोड करता है। यदि हम टोकन को सफलतापूर्वक सत्यापित कर सकते हैं, तो हम User ऑब्जेक्ट लौटाते हैं जो अनुरोध करने वाले उपयोगकर्ता का प्रतिनिधित्व करता है। हम ज्यादातर खुश पथ में रुचि रखते हैं और बहुत सारी जांच को बायपास करेंगे।
ApplicationController में authenticate विधि को परिभाषित करना और इसे before_action के रूप में सेट करना इससे विरासत में मिले हर कंट्रोलर को सुरक्षित करता है। किसी अन्य कंट्रोलर पर एक अनुरोध को उन कंट्रोलर तक पहुंचने के लिए एक वैध JWT की आवश्यकता होगी (क्योंकि हर दूसरा कंट्रोलर इस मुख्य कंट्रोलर को विरासत में देगा)।
अब, हमें एक AuthenticationController की आवश्यकता है जिसमें उपयोगकर्ता अनुरोध भेज सकें और हमारे सर्वर से एक हस्ताक्षरित JSON वेब टोकन प्राप्त कर सकें। यह कंट्रोलर app/controllers/authentication_controller.rb पर रखा जाना चाहिए और ऐसा दिख सकता है:
जब इस कंट्रोलर पर एक अनुरोध आता है, क्योंकि यह एक उपयोगकर्ता है जो टोकन मांग रहा है, हम शुरू में उन्हें प्रमाणित नहीं करना चाहते। इस कंट्रोलर का उद्देश्य एक टोकन के साथ प्रतिक्रिया देना है जिसका उपयोग उपयोगकर्ता हमारे सर्वर पर बाकी संसाधनों तक पहुंचने के लिए कर सकता है। इसलिए दूसरी पंक्ति पर skip_before_action :authenticate की आवश्यकता।
login एक्शन में (वह जिसे उपयोगकर्ता टोकन के लिए हिट करते हैं), हम इस कंट्रोलर पर आने वाले अनुरोध के साथ आने वाले पैरामीटर्स से username और password लेते हैं। यदि हम उपयोगकर्ता को प्रमाणित कर सकते हैं — यानी, सत्यापित करें कि उनका उपयोगकर्ता नाम और पासवर्ड हमारे डेटाबेस में संग्रहीत से मेल खाता है — तो हम उन्हें एक हस्ताक्षरित टोकन और उस टोकन की समाप्ति के बारे में जानकारी प्रस्तुत करते हैं।
हमारे मामले में, हम टोकन की समाप्ति अवधि का उपयोग नहीं करेंगे। लेकिन एक उत्पादन एप्लिकेशन में, इसका उपयोग किसी संसाधन तक पहुंच को रद्द करने के लिए किया जा सकता है।
हम बाद में curl का उपयोग करके इन सभी चरणों से गुजरेंगे।
संरक्षित संसाधन के साथ हमारे रूबी एप्लिकेशन का परीक्षण
हमने पहले 'रेल्स ऐप में JWT प्रमाणीकरण लागू करना' खंड के फ्लो डायग्राम में प्रवाह को आंशिक रूप से कवर किया था। सब कुछ पूरी तरह से कवर करने और फ्लो डायग्राम में सभी चरणों का परीक्षण करने के लिए, हमें एक संसाधन की रक्षा करने की आवश्यकता है।
हमारे पास पहले से ही एक Product मॉडल है। अब हमें उत्पाद मॉडल के लिए एक कंट्रोलर और उत्पाद और टोकन तक पहुंचने के लिए रूट्स की आवश्यकता है।
rails g controller Product index के साथ एक कंट्रोलर बनाएं ताकि हमारे पास ऐसा कुछ हो:
बेशक, हमें इन कंट्रोलर तक पहुंचने के लिए एक रूट की आवश्यकता है। हमारा config/routes.rb कुछ इस तरह दिखना चाहिए:
अब हम curl के साथ परीक्षण करेंगे कि सब कुछ अपेक्षा के अनुरूप काम करता है। ध्यान दें कि हमारे पास पहले से ही प्रमाणित करने के लिए एक उपयोगकर्ता और एक्सेस करने के लिए एक उत्पाद संसाधन है।
आइए किसी ऐसे उपयोगकर्ता के साथ JWT प्राप्त करने का प्रयास करें जो मौजूद नहीं है:
हमें निम्नलिखित प्रतिक्रिया मिलनी चाहिए:
अब पहले बनाए गए उपयोगकर्ता के साथ वही प्रयास करें:
यह हमें एक हस्ताक्षरित JSON वेब टोकन देना चाहिए जो ऐसा दिख सकता है:
आइए इस टोकन को एक सेकंड के लिए रखें और खराब टोकन के साथ उत्पाद संसाधन तक पहुंचने का प्रयास करें (मैंने टोकन में एक यादृच्छिक वर्ण बदल दिया):
और हमें मिलना चाहिए:
हालांकि, यदि हम पहले सर्वर से प्राप्त वैध टोकन के साथ उत्पाद संसाधन तक पहुंचने के लिए वही अनुरोध करते हैं:
हमें उत्पाद संसाधन तक पहुंच प्रदान की जाती है:
बस! हमने सफलतापूर्वक अपने रूबी एप्लिकेशन को JSON वेब टोकन के साथ सुरक्षित कर लिया है!
समापन
इस पोस्ट में, हमने JSON वेब टोकन और वे कैसे काम करते हैं पर चर्चा की। हमने पहले JWTs की मूल बातें कवर कीं, जिसमें उनकी संरचना और कुछ सर्वोत्तम अभ्यास शामिल हैं। फिर हमने jwt जेम का उपयोग करके एक सरल JWT प्रमाणीकरण लागू किया।
मुझे आशा है कि आपको यह पोस्ट उपयोगी लगी होगी। हैप्पी कोडिंग!
P.S. यदि आप Ruby Magic पोस्ट को प्रेस से निकलते ही पढ़ना चाहते हैं, तो हमारे Ruby Magic न्यूज़लेटर की सदस्यता लें और कभी भी एक भी पोस्ट न चूकें!