Firebase Cloud Storage के सुरक्षा नियमों में शर्तों का इस्तेमाल करना

यह गाइड, Firebase के सुरक्षा नियमों की भाषा के मुख्य सिंटैक्स के बारे में जानें गाइड पर आधारित है. इससे, Cloud Storage के लिए Firebase के सुरक्षा नियमों में शर्तें जोड़ने का तरीका दिखाया जा सकता है.

Cloud Storage के सुरक्षा नियमों का मुख्य बिल्डिंग ब्लॉक, स्थिति है. कंडीशन एक बूलियन एक्सप्रेशन है, जिससे यह तय होता है कि किसी खास कार्रवाई को अनुमति दी जानी चाहिए या नहीं. बुनियादी नियमों के मामले में, true और false की लिटरल वैल्यू का इस्तेमाल करना बहुत सही है. हालांकि, Cloud Storage भाषा के लिए Firebase के सुरक्षा नियम, आपको ऐसी मुश्किल स्थितियां लिखने के तरीके बताते हैं जिनकी मदद से:

  • उपयोगकर्ता की पुष्टि करने की प्रोसेस की जांच करें
  • आने वाले डेटा की पुष्टि करना

पुष्टि करना

Cloud Storage के लिए Firebase के सुरक्षा नियम, Firebase से पुष्टि करने की सुविधा के साथ इंटिग्रेट हो जाते हैं, ताकि Cloud Storage के लिए बेहतर उपयोगकर्ता आधारित पुष्टि की सुविधा दी जा सके. इससे, Firebase से पुष्टि करने वाले टोकन के दावों के आधार पर, ऐक्सेस को कंट्रोल करने की सुविधा मिलती है.

जब पुष्टि किया गया कोई उपयोगकर्ता, Cloud Storage के लिए अनुरोध करता है, तो request.auth वैरिएबल में, उपयोगकर्ता के uid (request.auth.uid) की जानकारी अपने-आप भर जाती है. साथ ही, Firebase से पुष्टि करने वाले JWT (request.auth.token) के दावों की जानकारी भी अपने-आप भर जाती है.

इसके अलावा, पसंद के मुताबिक पुष्टि करने की सुविधा का इस्तेमाल करने पर, request.auth.token फ़ील्ड में अन्य दावे दिखते हैं.

जब कोई ऐसा उपयोगकर्ता अनुरोध करता है जिसकी पुष्टि नहीं हुई है, तो request.auth वैरिएबल की वैल्यू null होती है.

इस डेटा का इस्तेमाल करके, फ़ाइलों को सुरक्षित करने के लिए पुष्टि करने के कई सामान्य तरीके इस्तेमाल किए जा सकते हैं:

  • सार्वजनिक: request.auth को अनदेखा करें
  • पुष्टि की गई निजी जानकारी: पक्का करें कि request.auth, null न हो
  • उपयोगकर्ता निजी: जाँचें कि request.auth.uid पथ uid के बराबर है
  • समूह निजी: किसी चुने गए दावे से मिलान करने के लिए कस्टम टोकन के दावों की जांच करें या यह देखने के लिए फ़ाइल मेटाडेटा पढ़ें कि मेटाडेटा फ़ील्ड मौजूद है या नहीं

सार्वजनिक

जो नियम request.auth कॉन्टेक्स्ट से मेल नहीं खाता उसे public नियम माना जा सकता है. ऐसा इसलिए, क्योंकि यह उपयोगकर्ता की पुष्टि करने के कॉन्टेक्स्ट पर विचार नहीं करता. ये नियम गेम ऐसेट, साउंड फ़ाइलों या अन्य स्टैटिक कॉन्टेंट जैसे सार्वजनिक डेटा को दिखाने में मददगार हो सकते हैं.

// Anyone to read a public image if the file is less than 100kB
// Anyone can upload a public file ending in '.txt'
match /public/{imageId} {
  allow read: if resource.size < 100 * 1024;
  allow write: if imageId.matches(".*\\.txt");
}

निजी तौर पर पुष्टि की गई

कुछ मामलों में, हो सकता है कि आप अपने ऐप्लिकेशन के सभी पुष्टि किए गए उपयोगकर्ताओं को डेटा दिखाना चाहें, लेकिन बिना पुष्टि वाले उपयोगकर्ताओं को नहीं. पुष्टि नहीं किए गए सभी उपयोगकर्ताओं के लिए request.auth वैरिएबल null है. इसलिए, जांच करें कि request.auth वैरिएबल मौजूद है, ताकि पुष्टि की जा सके:

// Require authentication on all internal image reads
match /internal/{imageId} {
  allow read: if request.auth != null;
}

निजी उपयोगकर्ता

अब तक, request.auth का सबसे सामान्य इस्तेमाल यह होगा कि हर उपयोगकर्ता को उनकी फ़ाइलों के लिए, हर तरह की ज़रूरी अनुमतियां दी जाएंगी. जैसे, प्रोफ़ाइल फ़ोटो अपलोड करना से लेकर निजी दस्तावेज़ पढ़ना.

Cloud Storage में मौजूद फ़ाइलों का पूरा "पाथ" होता है, इसलिए उपयोगकर्ता के ज़रिए कंट्रोल की जाने वाली फ़ाइल बनाने के लिए सिर्फ़ एक खास, उपयोगकर्ता की पहचान करने वाली जानकारी होती है. यह फ़ाइल नाम के प्रीफ़िक्स में उपयोगकर्ता की पहचान करने वाली जानकारी (जैसे कि उपयोगकर्ता का uid) होती है. इसकी जांच नियम का आकलन करते समय की जा सकती है:

// Only a user can upload their profile picture, but anyone can view it
match /users/{userId}/profilePicture.png {
  allow read;
  allow write: if request.auth.uid == userId;
}

समूह निजी

समान रूप से सामान्य इस्तेमाल का एक और उदाहरण है किसी ऑब्जेक्ट पर ग्रुप की अनुमतियों की अनुमति देना. जैसे, टीम के कई सदस्यों को किसी शेयर किए गए दस्तावेज़ पर सहयोग करने की अनुमति देना. ऐसा करने के कई तरीके हैं:

  • Firebase से पुष्टि करने वाले कस्टम टोकन को मिंट करें, जिसमें ग्रुप के किसी सदस्य (जैसे कि ग्रुप आईडी) के बारे में ज़्यादा जानकारी शामिल हो
  • फ़ाइल मेटाडेटा में ग्रुप की जानकारी (जैसे कि ग्रुप आईडी या अनुमति वाले uid की सूची) शामिल करें

इस डेटा के टोकन या फ़ाइल मेटाडेटा में सेव होने के बाद, इसे किसी नियम में शामिल किया जा सकता है:

// Allow reads if the group ID in your token matches the file metadata's `owner` property
// Allow writes if the group ID is in the user's custom token
match /files/{groupId}/{fileName} {
  allow read: if resource.metadata.owner == request.auth.token.groupId;
  allow write: if request.auth.token.groupId == groupId;
}

मूल्यांकन का अनुरोध करें

अपलोड करने, डाउनलोड करने, मेटाडेटा में बदलाव करने, और मिटाने की जानकारी का आकलन, Cloud Storage में भेजे गए request का इस्तेमाल करके किया जाता है. ऊपर बताए गए तरीके के मुताबिक, request.auth ऑब्जेक्ट में उपयोगकर्ता के यूनीक आईडी और Firebase से पुष्टि करने के पेलोड के अलावा, request वैरिएबल में वह फ़ाइल पाथ शामिल होता है जहां अनुरोध किया जा रहा है. साथ ही, अनुरोध मिलने का समय, और अनुरोध लिखे जाने पर नई resource वैल्यू भी शामिल होती है.

request ऑब्जेक्ट में, उपयोगकर्ता का यूनीक आईडी और request.auth ऑब्जेक्ट में Firebase से पुष्टि करने वाला पेलोड भी शामिल होता है. इसके बारे में ज़्यादा जानकारी दस्तावेज़ के उपयोगकर्ता पर आधारित सुरक्षा सेक्शन में दी गई है.

request ऑब्जेक्ट में प्रॉपर्टी की पूरी सूची नीचे दी गई है:

प्रॉपर्टी टाइप जानकारी
auth मैप<स्ट्रिंग, स्ट्रिंग> जब कोई उपयोगकर्ता लॉग इन होता है, तो उपयोगकर्ता को uid का यूनीक आईडी और token की जानकारी देता है, जो Firebase से पुष्टि करने की JWT के दावों का मैप होता है. ऐसा न करने पर, यह null होगा.
params मैप<स्ट्रिंग, स्ट्रिंग> अनुरोध के क्वेरी पैरामीटर वाला मैप.
path पाथ जिस पाथ पर अनुरोध किया जा रहा है उसे दिखाने वाला path.
resource मैप<स्ट्रिंग, स्ट्रिंग> नई संसाधन वैल्यू, सिर्फ़ write अनुरोध पर मौजूद है.
time timestamp अनुरोध का आकलन करने के लिए सर्वर के समय को दिखाने वाला टाइमस्टैंप.

संसाधनों का आकलन

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

Cloud Storage के लिए Firebase के सुरक्षा नियम, resource ऑब्जेक्ट में फ़ाइल का मेटाडेटा उपलब्ध कराते हैं. इसमें Cloud Storage ऑब्जेक्ट में दिखने वाले मेटाडेटा के कुंजी/वैल्यू पेयर होते हैं. डेटा का रखरखाव करने के लिए, इन प्रॉपर्टी की जांच read या write अनुरोध पर की जा सकती है.

write के अनुरोधों (जैसे कि अपलोड करना, मेटाडेटा अपडेट करना, और मिटाना) के लिए, resource ऑब्जेक्ट में, अनुरोध पाथ पर मौजूद फ़ाइल का मेटाडेटा शामिल किया जा सकता है. request.resource ऑब्जेक्ट का इस्तेमाल भी किया जा सकता है. इसमें फ़ाइल के मेटाडेटा का एक सबसेट शामिल होता है, जिसे लिखने की अनुमति होने पर लिखा जाएगा. डेटा इंटिग्रिटी पक्का करने के लिए या फ़ाइल टाइप या साइज़ जैसी ऐप्लिकेशन कंस्ट्रेंट को लागू करने के लिए, इन दो वैल्यू का इस्तेमाल किया जा सकता है.

resource ऑब्जेक्ट में प्रॉपर्टी की पूरी सूची नीचे दी गई है:

प्रॉपर्टी टाइप जानकारी
name स्ट्रिंग ऑब्जेक्ट का पूरा नाम
bucket स्ट्रिंग उस बकेट का नाम जिसमें यह ऑब्जेक्ट है.
generation int इस ऑब्जेक्ट की Google Cloud Storage ऑब्जेक्ट जनरेशन.
metageneration int इस ऑब्जेक्ट का Google Cloud Storage ऑब्जेक्ट मेटाजनरेशन.
size int ऑब्जेक्ट का साइज़, बाइट में.
timeCreated timestamp ऑब्जेक्ट बनाए जाने के समय को दिखाने वाला टाइमस्टैंप.
updated timestamp ऑब्जेक्ट को आखिरी बार अपडेट किए जाने का समय दिखाने वाला टाइमस्टैंप.
md5Hash स्ट्रिंग ऑब्जेक्ट का MD5 हैश.
crc32c स्ट्रिंग ऑब्जेक्ट का crc32c हैश.
etag स्ट्रिंग इस ऑब्जेक्ट से जुड़ा ईटैग.
contentDisposition स्ट्रिंग इस ऑब्जेक्ट से जुड़ा कॉन्टेंट मैनेजमेंट.
contentEncoding स्ट्रिंग इस ऑब्जेक्ट के साथ जुड़ी कॉन्टेंट एन्कोडिंग.
contentLanguage स्ट्रिंग इस ऑब्जेक्ट के कॉन्टेंट की भाषा.
contentType स्ट्रिंग इस ऑब्जेक्ट से जुड़ा कॉन्टेंट टाइप.
metadata मैप<स्ट्रिंग, स्ट्रिंग> डेवलपर की ओर से बताए गए कस्टम मेटाडेटा के कुंजी/वैल्यू पेयर.

request.resource में generation, metageneration, etag, timeCreated, और updated को छोड़कर, ये सभी शामिल हैं.

Cloud Firestore की मदद से बेहतर बनाएं

अनुमति देने से जुड़ी अन्य शर्तों का आकलन करने के लिए, Cloud Firestore में दस्तावेज़ों को ऐक्सेस किया जा सकता है.

firestore.get() और firestore.exists() फ़ंक्शन का इस्तेमाल करके आपके सुरक्षा नियम, Cloud Firestore के दस्तावेज़ों के साथ आने वाले अनुरोधों की जांच कर सकते हैं. firestore.get() और firestore.exists(), दोनों फ़ंक्शन में दस्तावेज़ के पूरी तरह से तय पाथ की ज़रूरत होती है. firestore.get() और firestore.exists() के लिए पाथ बनाते समय, वैरिएबल का इस्तेमाल करते समय आपको $(variable) सिंटैक्स का इस्तेमाल करके वैरिएबल को साफ़ तौर पर एस्केप करना होगा.

नीचे दिए गए उदाहरण में, हमने एक नियम देखा है. इस नियम के तहत, उन लोगों के लिए फ़ाइलों को पढ़ने का ऐक्सेस प्रतिबंधित होता है जो किसी खास क्लब के सदस्य हैं.

service firebase.storage {
  match /b/{bucket}/o {
    match /users/{club}/files/{fileId} {
      allow read: if club in
        firestore.get(/databases/(default)/documents/users/$(request.auth.id)).memberships
    }
  }
}
अगले उदाहरण में, उपयोगकर्ता के दोस्त ही उपयोगकर्ता की फ़ोटो देख सकते हैं.
service firebase.storage {
  match /b/{bucket}/o {
    match /users/{userId}/photos/{fileId} {
      allow read: if
        firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.id))
    }
  }
}

जब Cloud Storage के इन सुरक्षा नियमों को बनाने और सेव करने के बाद इन Cloud Firestore फ़ंक्शन का इस्तेमाल किया जाता है, तो आपको Firebase कंसोल या Firebase सीएलआई में इन दोनों प्रॉडक्ट को कनेक्ट करने के लिए अनुमतियां चालू करने के लिए कहा जाएगा.

Firebase के सुरक्षा नियमों को मैनेज और डिप्लॉय करने का तरीका सेक्शन में बताए गए तरीके से आईएएम की भूमिका को हटाकर, इस सुविधा को बंद किया जा सकता है.

डेटा की पुष्टि करें

Cloud Storage के लिए Firebase के सुरक्षा नियमों का इस्तेमाल, डेटा की पुष्टि करने के लिए भी किया जा सकता है. इनमें फ़ाइल के नाम और पाथ के साथ-साथ, contentType और size जैसी फ़ाइल मेटाडेटा प्रॉपर्टी की पुष्टि करना भी शामिल है.

service firebase.storage {
  match /b/{bucket}/o {
    match /images/{imageId} {
      // Only allow uploads of any image file that's less than 5MB
      allow write: if request.resource.size < 5 * 1024 * 1024
                   && request.resource.contentType.matches('image/.*');
    }
  }
}

कस्टम फ़ंक्शन

जैसे-जैसे आपके Firebase के सुरक्षा नियम ज़्यादा जटिल होते जाते हैं, वैसे-वैसे आप शर्तों के सेट को फ़ंक्शन में रैप कर सकते हैं, जिनका आप अपने नियमसेट में फिर से इस्तेमाल कर सकते हैं. सुरक्षा नियमों में कस्टम फ़ंक्शन इस्तेमाल किए जा सकते हैं. कस्टम फ़ंक्शन का सिंटैक्स कुछ-कुछ JavaScript जैसा है, लेकिन Firebase सुरक्षा नियम फ़ंक्शन, खास तौर पर डोमेन के लिए बनाई गई भाषा में लिखे गए हैं जिसमें कुछ अहम सीमाएं हैं:

  • फ़ंक्शन में सिर्फ़ एक return स्टेटमेंट हो सकता है. इनमें कोई खास तर्क नहीं हो सकता. उदाहरण के लिए, वे लूप नहीं चला सकते या बाहरी सेवाओं को कॉल नहीं कर सकते.
  • फ़ंक्शन, उस स्कोप से अपने-आप फ़ंक्शन और वैरिएबल को ऐक्सेस कर सकते हैं जिसमें उन्हें तय किया गया है. उदाहरण के लिए, service firebase.storage स्कोप में तय किए गए फ़ंक्शन के पास resource वैरिएबल का ऐक्सेस है. साथ ही, सिर्फ़ Cloud Firestore के लिए get() और exists() जैसे बिल्ट-इन फ़ंक्शन का ऐक्सेस है.
  • फ़ंक्शन दूसरे फ़ंक्शन को कॉल कर सकते हैं, लेकिन हो सकता है कि वे बार-बार न हों. कॉल स्टैक की कुल डेप्थ 10 है.
  • वर्शन rules2 में, फ़ंक्शन let कीवर्ड का इस्तेमाल करके वैरिएबल तय कर सकते हैं. फ़ंक्शन में कितनी भी लेट बाइंडिंग हो सकती हैं, लेकिन उनके आखिर में रिटर्न स्टेटमेंट होना चाहिए.

फ़ंक्शन को function कीवर्ड से तय किया जाता है और इसके लिए शून्य या उससे ज़्यादा आर्ग्युमेंट इस्तेमाल किए जाते हैं. उदाहरण के लिए, हो सकता है कि आप ऊपर दिए गए उदाहरणों में इस्तेमाल की गई दो तरह की शर्तों को एक ही फ़ंक्शन में मिलाना चाहें:

service firebase.storage {
  match /b/{bucket}/o {
    // True if the user is signed in or the requested data is 'public'
    function signedInOrPublic() {
      return request.auth.uid != null || resource.data.visibility == 'public';
    }
    match /images/{imageId} {
      allow read, write: if signedInOrPublic();
    }
    match /mp3s/{mp3Ids} {
      allow read: if signedInOrPublic();
    }
  }
}

Firebase के सुरक्षा नियमों में फ़ंक्शन का इस्तेमाल करने से, फ़ंक्शन को मैनेज करना आसान हो जाता है. ऐसा इसलिए होता है, क्योंकि आपके नियमों की जटिलता बढ़ती जा रही है.

अगले चरण

शर्तों पर की गई इस चर्चा के बाद, आपको नियमों के बारे में ज़्यादा बेहतर जानकारी मिली है और आप ये काम करने के लिए तैयार हैं:

इस्तेमाल के मुख्य उदाहरणों को मैनेज करने का तरीका जानें. साथ ही, नियमों को डेवलप करने, टेस्ट करने, और डिप्लॉय करने का वर्कफ़्लो जानें: