http एक आरईएसटी एपीआई के साथ प्रमाणीकरण कैसे करें?(ब्राउज़र+मूल ग्राहक)



session rest (0)

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

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

अब मैं मूल ग्राहकों का समर्थन करने के लिए पूरी चीज का विस्तार करना चाहता हूं। मैंने स्टेटलेस ऑथ, http मूल और डाइजेस्ट ऑथ, http सत्र, कुकीज़, एक्सएसआरएफ इत्यादि के बारे में बहुत कुछ पढ़ा है ... और अब मुझे लगता है कि मेरे पास एक सुरक्षित ऐप नहीं है, क्योंकि इसके कुछ हिस्सों को हाइजैक करने का हमेशा एक तरीका है ।

1 .: HTTP सत्र बनाम। स्टेटलेस ऑथ टोकन

क्या फर्क पड़ता है? मुझे यह नहीं मिला।

  • HTTP सत्र:

    1. क्लाइंट एक यूआरएल अनुरोध करता है (सर्वर के लिए पहला अनुरोध)
    2. सर्वर सामान्य प्रतिक्रिया देता है और कुछ अद्वितीय स्ट्रिंग (== सत्र आईडी) देता है
    3. क्लाइंट को प्रत्येक स्ट्रिंग के साथ इस स्ट्रिंग को भेजना होगा (जिसे HTTP शीर्षलेख का उपयोग करके स्वचालित रूप से किया जाता है)
    4. क्लाइंट लॉग इन -> सर्वर याद करता है कि यह विशेष सत्र आईडी अब लॉग इन है
    5. क्लाइंट उस पृष्ठ पर जाता है जिसके लिए ऑथ की आवश्यकता होती है -> कुछ भी करने के लिए विशेष नहीं है, क्योंकि सत्र आईडी स्वचालित रूप से HTTP शीर्षलेख के माध्यम से सर्वर पर भेजी जाएगी
  • स्टेटलेस ऑथ टोकन:

    1. ग्राहक अनुरोध यूआरएल (सर्वर के लिए पहला अनुरोध)
    2. सर्वर किसी भी कुंजी या टोकन या आईडी के बिना सामान्य प्रतिक्रिया देता है
    3. (यहां कुछ खास नहीं है)
    4. क्लाइंट लॉग इन -> सर्वर एक ऑथ टोकन बनाता है और प्रतिक्रिया के अंदर क्लाइंट को यह टोकन भेजता है
    5. क्लाइंट विज़िट पेज जिसके लिए ऑथ की आवश्यकता होती है -> क्लाइंट को ऑथ टोकन सबमिट करना होगा

मेरे लिए दोनों तरीके बहुत समान दिखते हैं। रेल के साथ मैं डेटाबेस के भीतर सत्र को स्टोर करना भी चुन सकता हूं ... देवता स्टेटलेस ऑथ टोकन के साथ ऐसा ही करेगा।

2 .: प्रमाणीकरण विधि

अभी मैं {"user":{"email":"[email protected]","password":"p455w0rd"}} साथ POST /users/sign_in का उपयोग कर रहा हूं {"user":{"email":"[email protected]","password":"p455w0rd"}}

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

मैंने जो पढ़ा है उससे:

  • साइन_इन सुरक्षा के संबंध में वर्तमान POST /users/sign_in और HTTP मूल POST /users/sign_in बीच कोई अंतर नहीं है। दोनों cleartext का उपयोग करें।
  • Sign_out के लिए HTTP मूल लेख का नुकसान होता है: साइन आउट केवल ब्राउज़र विंडो को बंद करना संभव है
  • HTTP डाइजेस्ट ऑथ का एक बड़ा फायदा है: यह पासवर्ड बिल्कुल भी प्रसारित नहीं करता है (केवल पासवर्ड का हैश और यादृच्छिक जेनरेट स्ट्रिंग)
  • (जर्मन) विकिपीडिया कहता है: HTTP डायजेस्ट ऑथ सभी ब्राउज़रों द्वारा समर्थित नहीं है। शायद यह जानकारी पुरानी है ?!

क्या चाहिए मुझे:

  • डेटाबेस में संग्रहीत उपयोगकर्ता नाम और हैश पासवर्ड (bcrypt)।
  • उपयोगकर्ता अपना पासवर्ड बदल सकता है और पासवर्ड को सादे टेक्स्ट में नहीं भेजा जाना चाहिए। (जब उपयोगकर्ता साइन_अप की बात आती है तो वही समस्या होती है)। संभव समाधान?
    1. बेशक: एसएसएल / टीएलएस का उपयोग करना
    2. क्लाइंट अनुरोध एक want_to_change_password_salt और क्लाइंट पक्ष पर पासवर्ड एन्क्रिप्ट करने के लिए इसका उपयोग करता है। लेकिन (?!) इस तरह से मैंने तार और हैश पासवर्ड पर हैश किए गए पासवर्ड का एक अनिवार्य हिस्सा भेजा होगा। मुझे असुरक्षित लगता है ?!

3 .: सीएसआरएफ टोकन

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

अब मैं अपने सर्वर एप्लिकेशन को मूल ग्राहकों के साथ काम करने के लिए बदलना चाहता हूं। एक मूल ग्राहक HTML पृष्ठ लोड नहीं करेगा और इस प्रकार एक CSRF टोकन पुनर्प्राप्त नहीं करेगा। तो मेरे दिमाग में निम्नलिखित विकल्प आए:

  • एक एक्सएसआरएफ टोकन आरईएसटी संसाधन बनाएँ। तो (मूल) क्लाइंट को पहले संसाधन को करने से पहले इस संसाधन से एक्सएसआरएफ टोकन का अनुरोध करना होगा।
  • पूरी तरह से एक्सएसआरएफ संरक्षण अक्षम करें।

प्रशन:

  • एक्सएसआरएफ सुरक्षा कैसे काम करती है (रेल में)? सर्वर कैसे जानता है कि कौन सा टोकन किस क्लाइंट से संबंधित है? सत्रों के बारे में सोचने का एकमात्र तरीका है। यह धारणा इस ओर जाती है:
  • अगर मैं पूरी तरह से स्टेटलेस आरईएसटी एपीआई बनाने के लिए सत्र अक्षम करता हूं, तो एक्सएसआरएफ सुरक्षा अब और काम नहीं करेगी। सही?

4 .: स्टेटलेस ऑथ टोकन

यहां मेरे पास बहुत सारे प्रश्न हैं:

  • क्या HTTP सत्रों के समान सुरक्षा समस्याएं हैं? मेरा क्या मतलब है: सत्र आईडी चोरी करना एथ टोकन चोरी करने के समान प्रभाव पड़ता है। सही?
  • ऑथ टोकन की समाप्ति को HTTP सत्रों के साथ ही काम करना चाहिए: सर्वर को टाइमस्टैम्प कहीं भी (डेटाबेस क्रमशः सत्र) स्टोर करना होगा और उसे जांचना होगा।
  • sign_out भी वही काम करता है?
    • सत्र: सर्वर पर सत्र नष्ट करें
    • ऑथ टोकन: सर्वर पर टोकन को नष्ट करें
  • जो मैंने पढ़ा है, उससे HTTP शीर्षलेख (जैसे सत्र आईडी) के अंदर ऑथ टोकन को स्टोर करना अधिक सुरक्षित होना चाहिए, क्योंकि सर्वर लॉग में GET पैरामीटर हो सकते हैं और इस प्रकार टोकन हो सकता है।
  • क्या यह सिर्फ एक सादा औथ टोकन होना चाहिए या यह बेहतर होगा अगर ग्राहक अपने उपयोगकर्ता_आईडी या यहां तक ​​कि हैश पासवर्ड भी प्रसारित करता है? HERE मैंने पढ़ा है कि ग्राहक को भेजना चाहिए:
    1. user_id
    2. expiration_date
    3. [ user_id , expiration_date , SECRET_KEY ] का हैश (या SECRET_KEY क्या है?)। जहां SECRET_KEY मूल रूप से सर्वर द्वारा उत्पन्न एक यादृच्छिक स्ट्रिंग है।

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

धन्यवाद :)

यहां कुछ नई जानकारी और नए प्रश्न हैं ;-) :

5 .: मूल ग्राहक

जहां तक ​​मूल ग्राहक चिंतित हैं, सत्रों का उपयोग करने के लिए कोई ( आसान ) तरीका नहीं है:

  • एक मूल ग्राहक कोई ब्राउज़र नहीं है

  • इस प्रकार यह आसानी से कुकीज़ को संभाल नहीं पाएगा (और कुकीज़ के बिना कोई सामान्य सत्र हैंडलिंग नहीं है)

तो 3 संभावित विकल्प हैं:

  1. देशी ग्राहकों के लिए सत्र हैंडलिंग लागू करें। यह इस तरह होगा:

    1. लॉग इन करें
    2. कुकीज़ प्राप्त करने के लिए प्रतिक्रिया के HTTP शीर्षलेख पढ़ें
    3. आपको आवश्यक सभी कुकी डेटा को सहेजें (विशेष रूप से सत्र सामग्री वाले एक को) स्थानीय रूप से
    4. इस सत्र आईडी को आपके द्वारा किए गए हर अनुरोध के साथ भेजें
  2. सत्रों का बिल्कुल उपयोग न करें। एक मूल ग्राहक के दृष्टिकोण से यह काफी समान है 1 .:

    1. लॉग इन करें
    2. HTTP शीर्षलेख या प्रतिक्रिया निकाय से कुछ प्रमाणीकरण टोकन प्राप्त करें (यह आपका ऐप है, हालांकि यह आपके ऊपर है)
    3. स्थानीय रूप से इस टोकन को बचाओ
    4. प्रत्येक अनुरोध के साथ इस टोकन भेजें
  3. संकर दृष्टिकोण। इसका मूल रूप से मतलब है कि सर्वर को ब्राउज़र और मूल क्लाइंट के बीच अंतर करना होगा और फिर प्रदत्त सत्र आईडी और सत्र डेटा या (मूल क्लाइंट के लिए) चेक करें, प्रदान किए गए ऑथ टोकन की जांच करें।

6 .: स्टेटलेस के साथ सीएसआरएफ टोकन (= कोई सत्र / कोई कुकीज़ नहीं) ऑथ

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

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

और इस प्रकार हमलावर वेबसाइट को निम्नलिखित करना है:

  1. एक कस्टम HTML <form> लिखें जो आपके एपीआई को इंगित करता है
  2. उपयोगकर्ता को किसी भी तरह Submit बटन पर क्लिक करने दें

बेशक यह फॉर्म कुछ ऐसा होगा:

<form action="http://your.api.com/transferMoney" method="post">
  <input type="hidden" name="receiver" value="ownerOfTheEvilSite" />
  <input type="hidden" name="amount" value="1000.00" />
  <input type="submit" value="WIN MONEY!!" />
</form>

इससे निम्नलिखित धारणाएं होती हैं :

  1. सीएसआरएफ संरक्षण केवल तभी जरूरी है क्योंकि ब्राउज़र स्वचालित रूप से कुकीज़ भेजते हैं।

  2. मूल ग्राहकों को सीएसआरएफ संरक्षण की आवश्यकता नहीं है (बेशक: आपका ब्राउज़र आपके मूल ऐप के प्रमाणीकरण डेटा (टोकन, कुकी, जो कुछ भी) तक नहीं पहुंच सकता है, और आपका मूल ऐप एपीआई के साथ संवाद करने के लिए ब्राउज़र का उपयोग नहीं करेगा)

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

यदि आप अपने ऐप की निगरानी करना चाहते हैं, तो आप निश्चित रूप से स्टेटलेस प्रमाणीकरण तंत्र के साथ सीएसआरएफ टोकन का उपयोग कर सकते हैं, लेकिन मुझे पूरा यकीन है कि कोई अतिरिक्त सुरक्षा लाभ नहीं है।

7 .: चुनने के लिए सही HTTP तरीके

लॉगिन / साइन इन करें और लॉगआउट / साइन आउट करें:

कभी भी कम से कम तीन कारणों के लिए GET उपयोग करें:

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

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

  3. जीईटी अनुरोध का उपयोग करते समय और प्रमाणीकरण जानकारी को URL पैरामीटर के रूप में प्रेषित करते समय (यानी http://your.api.com/login?username=foo&password=bar ) एक और समस्या है: सर्वर लॉग! अधिकांश सर्वर बस सभी HTTP पैरामीटर सहित प्रत्येक HTTP अनुरोध को लॉग करते हैं। इसका अर्थ है: यदि आपके सर्वर को हैक किया गया है, तो आपके डीबी से पासवर्ड हैश को क्रैक करने की कोई आवश्यकता नहीं है, उन्हें बस सर्वर की लॉग फाइलों पर एक नज़र डालना होगा। इसके अलावा एक दुर्भावनापूर्ण व्यवस्थापक प्रत्येक उपयोगकर्ता के लिए लॉगिन जानकारी भी पढ़ सकता है। समाधान की:

    • POST (या जो भी तरीका आपको पसंद है) का उपयोग करें और अनुरोध निकाय के अंदर प्रमाणीकरण जानकारी भेजें। या:
    • HTTP हेडर के भीतर प्रमाणीकरण जानकारी भेजें। क्योंकि उन जानकारी सामान्य रूप से सर्वर लॉग फ़ाइलों में प्रकट नहीं होती है। या:
    • सर्वर कॉन्फ़िगरेशन पर एक नज़र डालें, और इसे "पासवर्ड" नामक प्रत्येक यूआरएल पैरामीटर को हटाने के लिए कहें (या obfuscate है, तो यूआरएल login?username=foo&password=*** हो जाता है login?username=foo&password=*** लॉग के अंदर)। लेकिन मैं सुझाव देता हूं कि POST विधि के साथ इस तरह की जानकारी के लिए अनुरोध निकाय का उपयोग करें।

तो आप उदाहरण के लिए उपयोग कर सकते हैं:

लॉगिन के लिए POST http://your.api.com/authentication

लॉगआउट के लिए DELETE http://your.api.com/authentication

8 .: पासवर्ड और हैशिंग

प्रमाणीकरण केवल कुछ गुप्त कुंजी के साथ काम करता है। और निश्चित रूप से इस कुंजी को गुप्त रखा जाना चाहिए। इसका मतलब है की:

  • कभी भी अपने डेटाबेस में सादे टेक्स्ट में पासवर्ड स्टोर करें। इसे सुरक्षित बनाने के लिए कई पुस्तकालय उपलब्ध हैं। मेरी राय में सबसे अच्छा विकल्प bcrypt

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

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

  • राउंड : यह बस कितनी बार पासवर्ड धोया जाना चाहिए। 5000 राउंड का उपयोग करते समय हैशिंग फ़ंक्शन पासवर्ड के हैश के हैश के हैश के हैश को वापस कर देगा । ऐसा करने का मूल कारण है: यह सीपीयू पावर खर्च करता है! इसका मतलब है: जब कोई आपके हैश को मजबूत करने की कोशिश करता है, तो 5000 राउंड का उपयोग करते समय इसमें 5000 गुना अधिक समय लगता है। आपके आवेदन के लिए यह इससे कोई फर्क नहीं पड़ता: यदि उपयोगकर्ता अपना पासवर्ड जानता है, तो वह पहचान नहीं पाएगा, अगर सर्वर ने इसे सत्यापित करने के लिए 0.0004ms या 2ms लिया।

  • अच्छे पासवर्ड : यदि पासवर्ड बहुत आसान है तो सबसे अच्छा हैशिंग फ़ंक्शन बेकार है। यदि इसे एक शब्दकोश का उपयोग करके क्रैक किया जा सकता है, तो इससे कोई फर्क नहीं पड़ता कि आपने 5000 राउंड के साथ इसे धोया है: इसमें कुछ घंटे लगेंगे, लेकिन कुछ घंटे क्या हैं, अगर यह महीनों या साल हो सकता है? हालांकि सुनिश्चित करें कि आपके उपयोगकर्ता के पासवर्ड में सामान्य अनुशंसाएं हैं (निचला + ऊपरी मामला + संख्या + विशेष वर्ण, आदि पीपी।)

9 .: तार पर एन्क्रिप्टेड पासवर्ड भेजना

यदि आप HTTPS पर भरोसा नहीं कर सकते (या नहीं चाहते हैं), लेकिन साइन इन करते समय cleartext में पासवर्ड नहीं भेजना चाहते हैं, तो आप असममित क्रिप्टोग्राफी ( http://en.wikipedia.org/wiki/Public-key_cryptography उपयोग कर सकते हैं http://en.wikipedia.org/wiki/Public-key_cryptography )।

यह सर्वर एक कुंजी जोड़ी (सार्वजनिक कुंजी और निजी कुंजी) बनाता है। सार्वजनिक कुंजी ग्राहकों को उपलब्ध कराई जाती है, निजी कुंजी को निजी रखा जाना चाहिए!

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

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

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

और ध्यान रखें कि वास्तविक HTTPS कनेक्शन पूरे (!) कनेक्शन और सभी डेटा को एन्क्रिप्ट करता है, न केवल पासवर्ड डेटा। और यह क्लाइंट से सर्वर और सर्वर से क्लाइंट तक दोनों तरीकों को एन्क्रिप्ट करता है।





stateless