ऐप्लिकेशन डेवलपमेंट की प्रक्रिया में, सुरक्षा सबसे मुश्किल कामों में से एक हो सकती है. ज़्यादातर ऐप्लिकेशन में, डेवलपर को ऐसा सर्वर बनाना और चलाना होता है जो पुष्टि (उपयोगकर्ता कौन है) और अनुमति (उपयोगकर्ता क्या कर सकता है) को मैनेज करता है.
Firebase Security Rules मिडल (सर्वर) लेयर हटाएं और सीधे आपके डेटा से कनेक्ट करने वाले क्लाइंट के लिए, पाथ के आधार पर अनुमतियां तय करने की अनुमति दें. आने वाले अनुरोधों पर नियम कैसे लागू होते हैं, इस बारे में ज़्यादा जानने के लिए इस गाइड का इस्तेमाल करें.
किसी प्रॉडक्ट के नियमों के बारे में ज़्यादा जानने के लिए, वह प्रॉडक्ट चुनें.
Cloud Firestore
बुनियादी स्ट्रक्चर
Cloud Firestore और Cloud Storage में Firebase Security Rules के लिए, इस स्ट्रक्चर और सिंटैक्स का इस्तेमाल करें:
service <<name>> {
// Match the resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow <<methods>> : if <<condition>>
}
}
नियम बनाते समय, इन ज़रूरी कॉन्सेप्ट को समझना ज़रूरी है:
- अनुरोध:
allow
स्टेटमेंट में इस्तेमाल किया गया तरीका या तरीके. ये ऐसे तरीक़े हैं जिन्हें चलाने की अनुमति दी जा रही है. स्टैंडर्ड तरीके ये हैं:get
,list
,create
,update
, औरdelete
.read
औरwrite
के आसान तरीके, दिए गए डेटाबेस या स्टोरेज पाथ पर, पढ़ने और लिखने का ऐक्सेस देते हैं. - पाथ: डेटाबेस या स्टोरेज की जगह, जिसे यूआरआई पाथ के तौर पर दिखाया जाता है.
- नियम:
allow
स्टेटमेंट, जिसमें एक शर्त शामिल होती है. अगर यह शर्त सही होती है, तो अनुरोध को अनुमति दी जाती है.
सुरक्षा के नियमों का दूसरा वर्शन
मई 2019 से, Firebase के सुरक्षा नियमों का दूसरा वर्शन उपलब्ध है. नियमों के दूसरे वर्शन में, बार-बार इस्तेमाल होने वाले वाइल्डकार्ड {name=**}
के काम करने का तरीका बदला गया है. अगर आपको कलेक्शन ग्रुप क्वेरी का इस्तेमाल करना है, तो आपको वर्शन 2 का इस्तेमाल करना होगा. आपको अपने सुरक्षा नियमों में rules_version = '2';
को पहली पंक्ति बनाकर, वर्शन 2 के लिए ऑप्ट-इन करना होगा:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
मिलते-जुलते पाथ
मैच करने वाले सभी स्टेटमेंट, दस्तावेज़ों पर ले जाने चाहिए, न कि कलेक्शन पर. मैच स्टेटमेंट, match /cities/SF
की तरह किसी खास दस्तावेज़ पर ले जा सकता है या match /cities/{city}
की तरह दिए गए पाथ में मौजूद किसी भी दस्तावेज़ पर ले जाने के लिए वाइल्डकार्ड का इस्तेमाल कर सकता है.
ऊपर दिए गए उदाहरण में, मैच स्टेटमेंट में {city}
वाइल्डकार्ड सिंटैक्स का इस्तेमाल किया गया है.
इसका मतलब है कि यह नियम cities
कलेक्शन के किसी भी दस्तावेज़ पर लागू होता है, जैसे कि
/cities/SF
या /cities/NYC
. जब मैच स्टेटमेंट में allow
एक्सप्रेशन का आकलन किया जाता है, तो city
वैरिएबल, शहर के दस्तावेज़ के नाम पर सेट हो जाएगा. जैसे, SF
या NYC
.
मिलते-जुलते सब-कलेक्शन
Cloud Firestore में डेटा को दस्तावेज़ों के कलेक्शन में व्यवस्थित किया जाता है. साथ ही, हर दस्तावेज़ में सब-कलेक्शन की मदद से हैरारकी को बढ़ाया जा सकता है. यह समझना ज़रूरी है कि सुरक्षा नियम, हैरारकी वाले डेटा के साथ कैसे इंटरैक्ट करते हैं.
मान लें कि cities
कलेक्शन के हर दस्तावेज़ में एक landmarks
सब-कलेक्शन है. सुरक्षा से जुड़े नियम सिर्फ़ मैच होने वाले पाथ पर लागू होते हैं. इसलिए, cities
कलेक्शन पर तय किए गए ऐक्सेस कंट्रोल, landmarks
सब-कलेक्शन पर लागू नहीं होते. इसके बजाय, सब-कलेक्शन का ऐक्सेस कंट्रोल करने के लिए साफ़ तौर पर नियम लिखें:
service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city} {
allow read, write: if <condition>;
// Explicitly define rules for the 'landmarks' subcollection
match /landmarks/{landmark} {
allow read, write: if <condition>;
}
}
}
}
match
स्टेटमेंट को नेस्ट करते समय, अंदरूनी match
स्टेटमेंट का पाथ, हमेशा बाहरी match
स्टेटमेंट के पाथ के हिसाब से होता है. इसलिए, ये नियमों के सेट एक जैसे हैं:
service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city} {
match /landmarks/{landmark} {
allow read, write: if <condition>;
}
}
}
}
service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city}/landmarks/{landmark} {
allow read, write: if <condition>;
}
}
}
बार-बार इस्तेमाल होने वाले वाइल्डकार्ड
अगर आपको किसी भी तरह की हैरारकी पर नियम लागू करने हैं, तो {name=**}
के रीकर्सिव वाइल्डकार्ड सिंटैक्स का इस्तेमाल करें:
service cloud.firestore {
match /databases/{database}/documents {
// Matches any document in the cities collection as well as any document
// in a subcollection.
match /cities/{document=**} {
allow read, write: if <condition>;
}
}
}
बार-बार इस्तेमाल होने वाले वाइल्डकार्ड सिंटैक्स का इस्तेमाल करने पर, वाइल्डकार्ड वैरिएबल में मैच होने वाला पूरा पाथ सेगमेंट शामिल होगा. भले ही, दस्तावेज़ किसी नेस्ट किए गए सबकलेक्शन में हो. उदाहरण के लिए, ऊपर दिए गए नियम, /cities/SF/landmarks/coit_tower
में मौजूद दस्तावेज़ से मैच करेंगे. साथ ही, document
वैरिएबल की वैल्यू SF/landmarks/coit_tower
होगी.
हालांकि, ध्यान दें कि बार-बार इस्तेमाल होने वाले वाइल्डकार्ड का व्यवहार, नियमों के वर्शन पर निर्भर करता है.
वर्शन 1
सुरक्षा के नियम, डिफ़ॉल्ट रूप से वर्शन 1 का इस्तेमाल करते हैं. पहले वर्शन में, बार-बार इस्तेमाल होने वाले वाइल्डकार्ड, एक या एक से ज़्यादा पाथ आइटम से मैच करते हैं. ये खाली पाथ से मेल नहीं खाते. इसलिए, match /cities/{city}/{document=**}
, सब-कलेक्शन में मौजूद दस्तावेज़ों से मेल खाता है, लेकिन cities
कलेक्शन में मौजूद दस्तावेज़ों से नहीं. वहीं, match /cities/{document=**}
, cities
कलेक्शन और सब-कलेक्शन, दोनों में मौजूद दस्तावेज़ों से मेल खाता है.
बार-बार इस्तेमाल होने वाले वाइल्डकार्ड, मैच स्टेटमेंट के आखिर में होने चाहिए.
वर्शन 2
सुरक्षा नियमों के वर्शन 2 में, बार-बार इस्तेमाल होने वाले वाइल्डकार्ड, शून्य या एक से ज़्यादा पाथ आइटम से मैच करते हैं. match/cities/{city}/{document=**}
, किसी भी सबकलेक्शन के साथ-साथ cities
कलेक्शन के दस्तावेज़ों से मेल खाता है.
आपको अपने सुरक्षा नियमों में सबसे ऊपर rules_version = '2';
जोड़कर, वर्शन 2 में ऑप्ट-इन करना होगा:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Matches any document in the cities collection as well as any document
// in a subcollection.
match /cities/{city}/{document=**} {
allow read, write: if <condition>;
}
}
}
हर मैच स्टेटमेंट में ज़्यादा से ज़्यादा एक बार फिर से शुरू होने वाला वाइल्डकार्ड हो सकता है. हालांकि, दूसरे वर्शन में, इस वाइल्डकार्ड को मैच स्टेटमेंट में कहीं भी रखा जा सकता है. उदाहरण के लिए:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Matches any document in the songs collection group
match /{path=**}/songs/{song} {
allow read, write: if <condition>;
}
}
}
अगर कलेक्शन ग्रुप क्वेरी का इस्तेमाल किया जाता है, तो आपको कलेक्शन ग्रुप क्वेरी को सुरक्षित करना लेख में बताए गए वर्शन 2 का इस्तेमाल करना होगा.
ओवरलैप होने वाले मैच स्टेटमेंट
ऐसा हो सकता है कि कोई दस्तावेज़, एक से ज़्यादा match
स्टेटमेंट से मैच करे. अगर एक से ज़्यादा allow
एक्सप्रेशन किसी अनुरोध से मैच करते हैं, तो ऐक्सेस तब दिया जाता है, जब कोई भी शर्त true
हो:
service cloud.firestore {
match /databases/{database}/documents {
// Matches any document in the 'cities' collection.
match /cities/{city} {
allow read, write: if false;
}
// Matches any document in the 'cities' collection or subcollections.
match /cities/{document=**} {
allow read, write: if true;
}
}
}
ऊपर दिए गए उदाहरण में, cities
कलेक्शन में सभी रीड और राइट की अनुमति होगी, क्योंकि दूसरा नियम हमेशा true
होता है. भले ही, पहला नियम हमेशा false
हो.
सुरक्षा नियम की सीमाएं
सुरक्षा नियमों के साथ काम करते समय, इन सीमाओं का ध्यान रखें:
सीमा | विवरण |
---|---|
हर अनुरोध के लिए, exists() , get() , और getAfter() कॉल की ज़्यादा से ज़्यादा संख्या |
इनमें से किसी भी सीमा को पार करने पर, 'अनुमति नहीं दी गई' गड़बड़ी का मैसेज दिखता है. दस्तावेज़ के ऐक्सेस के कुछ अनुरोध कैश मेमोरी में सेव किए जा सकते हैं. कैश मेमोरी में सेव किए गए अनुरोधों की गिनती, अनुरोधों की सीमा में नहीं की जाती. |
नेस्ट किए गए match स्टेटमेंट की ज़्यादा से ज़्यादा गहराई |
10 |
नेस्ट किए गए
match स्टेटमेंट के सेट में, पाथ सेगमेंट में पाथ की ज़्यादा से ज़्यादा लंबाई |
100 |
नेस्ट किए गए match स्टेटमेंट के सेट में, पाथ कैप्चर वैरिएबल की ज़्यादा से ज़्यादा संख्या |
20 |
फ़ंक्शन कॉल की ज़्यादा से ज़्यादा गहराई | 20 |
फ़ंक्शन के आर्ग्युमेंट की ज़्यादा से ज़्यादा संख्या | 7 |
हर फ़ंक्शन के लिए let वैरिएबल बाइंडिंग की ज़्यादा से ज़्यादा संख्या |
10 |
बार-बार या चक्रीय तौर पर फ़ंक्शन कॉल करने की ज़्यादा से ज़्यादा संख्या | 0 (अनुमति नहीं है) |
हर अनुरोध के लिए, एक्सप्रेशन की ज़्यादा से ज़्यादा संख्या | 1,000 |
नियमों के सेट का ज़्यादा से ज़्यादा साइज़ | नियमों के सेट का साइज़, इन दो सीमाओं के अंदर होना चाहिए:
|
Cloud Storage
बुनियादी स्ट्रक्चर
Cloud Firestore और Cloud Storage में Firebase Security Rules के लिए, इस स्ट्रक्चर और सिंटैक्स का इस्तेमाल करें:
service <<name>> {
// Match the resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow <<methods>> : if <<condition>>
}
}
नियम बनाते समय, इन ज़रूरी कॉन्सेप्ट को समझना ज़रूरी है:
- अनुरोध:
allow
स्टेटमेंट में इस्तेमाल किया गया तरीका या तरीके. ये ऐसे तरीक़े हैं जिन्हें चलाने की अनुमति दी जा रही है. स्टैंडर्ड तरीके ये हैं:get
,list
,create
,update
, औरdelete
.read
औरwrite
के आसान तरीके, दिए गए डेटाबेस या स्टोरेज पाथ पर, पढ़ने और लिखने का ऐक्सेस देते हैं. - पाथ: डेटाबेस या स्टोरेज की जगह, जिसे यूआरआई पाथ के तौर पर दिखाया जाता है.
- नियम:
allow
स्टेटमेंट, जिसमें एक शर्त शामिल होती है. अगर यह शर्त सही होती है, तो अनुरोध को अनुमति दी जाती है.
मिलते-जुलते पाथ
Cloud Storage Security Rules match
Cloud Storage में फ़ाइलों को ऐक्सेस करने के लिए इस्तेमाल किए जाने वाले फ़ाइल पाथ. नियमों में match
सटीक पाथ या वाइल्डकार्ड पाथ शामिल किए जा सकते हैं. साथ ही, नियमों को नेस्ट भी किया जा सकता है. अगर मैच करने वाले किसी नियम में अनुरोध के तरीके की अनुमति नहीं है या शर्त की वैल्यू false
है, तो अनुरोध अस्वीकार कर दिया जाता है.
एग्ज़ैक्ट मैच
// Exact match for "images/profilePhoto.png" match /images/profilePhoto.png { allow write: if <condition>; } // Exact match for "images/croppedProfilePhoto.png" match /images/croppedProfilePhoto.png { allow write: if <other_condition>; }
नेस्ट किए गए मैच
// Partial match for files that start with "images" match /images { // Exact match for "images/profilePhoto.png" match /profilePhoto.png { allow write: if <condition>; } // Exact match for "images/croppedProfilePhoto.png" match /croppedProfilePhoto.png { allow write: if <other_condition>; } }
वाइल्डकार्ड मैच
नियमों का इस्तेमाल, वाइल्डकार्ड का इस्तेमाल करके किसी पैटर्न को match
करने के लिए भी किया जा सकता है. वाइल्डकार्ड, नाम वाला एक वैरिएबल होता है. यह profilePhoto.png
जैसी एक स्ट्रिंग या images/profilePhoto.png
जैसे कई पाथ सेगमेंट को दिखाता है.
वाइल्डकार्ड बनाने के लिए, वाइल्डकार्ड के नाम के चारों ओर कर्ली ब्रैकेट जोड़ें, जैसे कि
{string}
. एक से ज़्यादा सेगमेंट वाले वाइल्डकार्ड का एलान करने के लिए, वाइल्डकार्ड के नाम में =**
जोड़ें, जैसे कि {path=**}
:
// Partial match for files that start with "images" match /images { // Exact match for "images/*" // e.g. images/profilePhoto.png is matched match /{imageId} { // This rule only matches a single path segment (*) // imageId is a string that contains the specific segment matched allow read: if <condition>; } // Exact match for "images/**" // e.g. images/users/user:12345/profilePhoto.png is matched // images/profilePhoto.png is also matched! match /{allImages=**} { // This rule matches one or more path segments (**) // allImages is a path that contains all segments matched allow read: if <other_condition>; } }
अगर एक से ज़्यादा नियम किसी फ़ाइल से मैच करते हैं, तो नतीजा सभी नियमों के आकलन के नतीजे का OR
होता है. इसका मतलब है कि अगर फ़ाइल किसी नियम से मैच करती है और उसका आकलन true
के तौर पर किया जाता है, तो नतीजा true
होगा.
ऊपर दिए गए नियमों के मुताबिक, "images/profilePhoto.png" फ़ाइल को तब ही पढ़ा जा सकता है, जब condition
या other_condition
का आकलन 'सही' के तौर पर किया गया हो. वहीं, "images/users/user:12345/profilePhoto.png" फ़ाइल को सिर्फ़ other_condition
के नतीजे के हिसाब से पढ़ा जा सकता है.
match
फ़ाइल का नाम या पाथ अनुमति देने वाले फ़ंक्शन में, वाइल्डकार्ड वैरिएबल का रेफ़रंस दिया जा सकता है:
// Another way to restrict the name of a file match /images/{imageId} { allow read: if imageId == "profilePhoto.png"; }
Cloud Storage Security Rules कैस्केड नहीं करते हैं. साथ ही, नियमों का आकलन सिर्फ़ तब किया जाता है, जब अनुरोध पाथ, नियमों वाले पाथ से मेल खाता हो.
आकलन का अनुरोध करना
अपलोड, डाउनलोड, मेटाडेटा में बदलाव, और मिटाए गए डेटा का आकलन करने के लिए, Cloud Storage पर भेजे गए request
का इस्तेमाल किया जाता है. request
वैरिएबल में, वह फ़ाइल पाथ होता है जहां अनुरोध किया जा रहा है, अनुरोध मिलने का समय, और अगर अनुरोध लिखने के लिए किया गया है, तो नई resource
वैल्यू शामिल होती है. एचटीटीपी हेडर और पुष्टि की स्थिति भी शामिल है.
request
ऑब्जेक्ट में उपयोगकर्ता का यूनीक आईडी और request.auth
ऑब्जेक्ट में Firebase Authentication पेलोड भी होता है. इस बारे में ज़्यादा जानकारी, दस्तावेज़ों के पुष्टि सेक्शन में दी गई है.
request
ऑब्जेक्ट में मौजूद प्रॉपर्टी की पूरी सूची यहां दी गई है:
प्रॉपर्टी | टाइप | ब्यौरा |
---|---|---|
auth |
map<string, string> | जब कोई उपयोगकर्ता लॉग इन होता है, तो uid , उपयोगकर्ता का यूनीक आईडी और
token , Firebase Authentication जेडब्लयूटी दावों का मैप उपलब्ध कराता है. ऐसा न करने पर, यह
null होगा. |
params |
map<string, string> | अनुरोध के क्वेरी पैरामीटर वाला मैप. |
path |
पाथ | path , उस पाथ को दिखाता है जहां अनुरोध किया जा रहा है. |
resource |
map<string, string> | नई संसाधन वैल्यू, सिर्फ़ write अनुरोधों पर मौजूद होती है.
|
time |
timestamp | टाइमस्टैंप, सर्वर के उस समय को दिखाता है जब अनुरोध का आकलन किया जाता है. |
संसाधन का आकलन
नियमों का आकलन करते समय, अपलोड की जा रही, डाउनलोड की जा रही, बदली जा रही या मिटाई जा रही फ़ाइल के मेटाडेटा का आकलन भी किया जा सकता है. इसकी मदद से, जटिल और बेहतर नियम बनाए जा सकते हैं. जैसे, सिर्फ़ कुछ तरह के कॉन्टेंट वाली फ़ाइलों को अपलोड करने की अनुमति देना या सिर्फ़ तय साइज़ से बड़ी फ़ाइलों को मिटाना.
Cloud Storage के लिए Firebase Security Rules, resource
ऑब्जेक्ट में फ़ाइल का मेटाडेटा उपलब्ध कराता है. इसमें Cloud Storage ऑब्जेक्ट में दिखाए गए मेटाडेटा के की/वैल्यू पेयर शामिल होते हैं. डेटा की अखंडता को पक्का करने के लिए, इन प्रॉपर्टी की जांच read
या
write
अनुरोधों पर की जा सकती है.
write
अनुरोधों (जैसे, अपलोड, मेटाडेटा अपडेट, और मिटाना) पर, resource
ऑब्जेक्ट के अलावा, आपके पास request.resource
ऑब्जेक्ट का इस्तेमाल करने का विकल्प भी होता है. 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 |
स्ट्रिंग | इस ऑब्जेक्ट से जुड़ा etag. |
contentDisposition |
स्ट्रिंग | इस ऑब्जेक्ट से जुड़ा कॉन्टेंट डिस्पोज़िशन. |
contentEncoding |
स्ट्रिंग | इस ऑब्जेक्ट से जुड़ा कॉन्टेंट कोड. |
contentLanguage |
स्ट्रिंग | इस ऑब्जेक्ट से जुड़े कॉन्टेंट की भाषा. |
contentType |
स्ट्रिंग | इस ऑब्जेक्ट से जुड़ा कॉन्टेंट टाइप. |
metadata |
map<string, string> | डेवलपर के तय किए गए अतिरिक्त कस्टम मेटाडेटा के की/वैल्यू पेयर. |
request.resource
में generation
,
metageneration
, etag
, timeCreated
, और updated
को छोड़कर ये सभी शामिल हैं.
सुरक्षा के नियमों की सीमाएं
सुरक्षा से जुड़े नियमों के साथ काम करते समय, इन सीमाओं का ध्यान रखें:
सीमा | विवरण |
---|---|
हर अनुरोध के लिए, firestore.exists() और
firestore.get() कॉल की ज़्यादा से ज़्यादा संख्या |
एक दस्तावेज़ के अनुरोध और क्वेरी के अनुरोध के लिए दो. इस सीमा से ज़्यादा डेटा अपलोड करने पर, 'अनुमति नहीं दी गई' गड़बड़ी का मैसेज दिखता है. एक ही दस्तावेज़ के ऐक्सेस कॉल को कैश मेमोरी में सेव किया जा सकता है. साथ ही, कैश मेमोरी में सेव किए गए कॉल की संख्या, सीमाओं में शामिल नहीं की जाती. |
पूरा उदाहरण
इन सभी बातों को ध्यान में रखते हुए, इमेज स्टोरेज के समाधान के लिए नियमों का पूरा उदाहरण बनाया जा सकता है:
service firebase.storage { match /b/{bucket}/o { match /images { // Cascade read to any image type at any path match /{allImages=**} { allow read; } // Allow write files to the path "images/*", subject to the constraints: // 1) File is less than 5MB // 2) Content type is an image // 3) Uploaded content type matches existing content type // 4) File name (stored in imageId wildcard variable) is less than 32 characters match /{imageId} { allow write: if request.resource.size < 5 * 1024 * 1024 && request.resource.contentType.matches('image/.*') && request.resource.contentType == resource.contentType && imageId.size() < 32 } } } }
Realtime Database
बुनियादी स्ट्रक्चर
Realtime Database में, Firebase Security Rules में JavaScript जैसे एक्सप्रेशन होते हैं, जो किसी JSON दस्तावेज़ में मौजूद होते हैं.
इनमें इस सिंटैक्स का इस्तेमाल किया जाता है:
{
"rules": {
"<<path>>": {
// Allow the request if the condition for each method is true.
".read": <<condition>>,
".write": <<condition>>,
".validate": <<condition>>
}
}
}
नियम में तीन बुनियादी एलिमेंट होते हैं:
- पाथ: डेटाबेस की जगह. यह आपके डेटाबेस के JSON स्ट्रक्चर को दिखाता है.
- अनुरोध: ये ऐसे तरीके हैं जिनका इस्तेमाल करके नियम, ऐक्सेस देता है.
read
औरwrite
नियमों से, डेटा को पढ़ने और उसमें बदलाव करने का ज़्यादा ऐक्सेस मिलता है. वहीं,validate
नियम, आने वाले या मौजूदा डेटा के आधार पर ऐक्सेस देने के लिए, दूसरी पुष्टि के तौर पर काम करते हैं. - शर्त: यह शर्त, अनुरोध को तब अनुमति देती है, जब वह सही हो.
पाथ पर नियम कैसे लागू होते हैं
Realtime Database में, Rules एक-एक करके लागू होते हैं. इसका मतलब है कि ज़्यादा लेवल वाले पैरंट नोड के नियम, ज़्यादा जानकारी वाले चाइल्ड नोड के नियमों को बदल देते हैं. साथ ही, किसी गहरे नोड के नियम, पैरंट पाथ का ऐक्सेस नहीं दे सकते. अगर आपने किसी पैरंट पाथ के लिए पहले ही ऐक्सेस दिया है, तो डेटाबेस के स्ट्रक्चर में किसी गहरे पाथ के लिए, ऐक्सेस को बेहतर नहीं बनाया जा सकता या उसे रद्द नहीं किया जा सकता.
इन नियमों का पालन करें:
{ "rules": { "foo": { // allows read to /foo/* ".read": "data.child('baz').val() === true", "bar": { // ignored, since read was allowed already ".read": false } } } }
सुरक्षा के इस स्ट्रक्चर की मदद से, /bar/
को तब पढ़ा जा सकता है, जब /foo/
में वैल्यू true
वाला चाइल्ड baz
शामिल हो.
/foo/bar/
में दिए गए ".read": false
नियम का यहां कोई असर नहीं पड़ता, क्योंकि चाइल्ड पाथ से ऐक्सेस रद्द नहीं किया जा सकता.
ऐसा हो सकता है कि यह आपको तुरंत समझ न आए, लेकिन यह नियमों की भाषा का एक अहम हिस्सा है. इससे, ऐक्सेस से जुड़ी बहुत ही जटिल अनुमतियां कम से कम प्रयास के साथ लागू की जा सकती हैं. यह सुविधा, उपयोगकर्ता के हिसाब से सुरक्षा के लिए खास तौर पर मददगार है.
हालांकि, .validate
नियम कैस्केड नहीं होते. डेटा में बदलाव करने की अनुमति देने के लिए, पुष्टि करने वाले सभी नियमों को हैरारकी के सभी लेवल पर पूरा करना ज़रूरी है.
इसके अलावा, पैरंट पाथ पर नियम लागू नहीं होते. इसलिए, अगर अनुरोध की गई जगह पर कोई नियम नहीं है या पैरंट जगह पर ऐक्सेस देने वाला कोई नियम नहीं है, तो पढ़ने या लिखने की कार्रवाई पूरी नहीं हो पाती. भले ही, जिन चाइल्ड पाथ पर असर पड़ा है उन्हें ऐक्सेस किया जा सकता हो, फिर भी पैरंट लोकेशन पर पढ़ने की सुविधा पूरी तरह से काम नहीं करेगी. इस स्ट्रक्चर पर विचार करें:
{ "rules": { "records": { "rec1": { ".read": true }, "rec2": { ".read": false } } } }
यह समझे बिना कि नियमों का आकलन एक-एक करके किया जाता है, ऐसा लग सकता है कि /records/
पाथ को फ़ेच करने पर rec1
दिखेगा, लेकिन rec2
नहीं. हालांकि, असल नतीजा गड़बड़ी है:
JavaScript
var db = firebase.database(); db.ref("records").once("value", function(snap) { // success method is not called }, function(err) { // error callback triggered with PERMISSION_DENIED });
Objective-C
FIRDatabaseReference *ref = [[FIRDatabase database] reference]; [[_ref child:@"records"] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) { // success block is not called } withCancelBlock:^(NSError * _Nonnull error) { // cancel block triggered with PERMISSION_DENIED }];
Swift
var ref = FIRDatabase.database().reference() ref.child("records").observeSingleEventOfType(.Value, withBlock: { snapshot in // success block is not called }, withCancelBlock: { error in // cancel block triggered with PERMISSION_DENIED })
Java
FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference ref = database.getReference("records"); ref.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot snapshot) { // success method is not called } @Override public void onCancelled(FirebaseError firebaseError) { // error callback triggered with PERMISSION_DENIED }); });
REST
curl https://docs-examples.firebaseio.com/rest/records/ # response returns a PERMISSION_DENIED error
/records/
में, डेटा पढ़ने की कार्रवाई एक बार में पूरी होती है. साथ ही, /records/
में मौजूद सभी डेटा को ऐक्सेस करने की अनुमति देने वाला कोई नियम नहीं है. इसलिए, इससे PERMISSION_DENIED
गड़बड़ी का मैसेज दिखेगा. अगर हम अपने Firebase कंसोल में सुरक्षा सिम्युलेटर में इस नियम का आकलन करते हैं, तो हमें पता चलता है कि पढ़ने की अनुमति अस्वीकार कर दी गई थी:
Attempt to read /records with auth=Success(null) / /records No .read rule allowed the operation. Read was denied.
कार्रवाई अस्वीकार कर दी गई, क्योंकि पढ़ने के लिए बने किसी भी नियम ने /records/
पाथ को ऐक्सेस करने की अनुमति नहीं दी. हालांकि, ध्यान दें कि rec1
के लिए बने नियम का कभी आकलन नहीं किया गया, क्योंकि वह उस पाथ में नहीं था जिसके लिए हमने अनुरोध किया था. rec1
को फ़ेच करने के लिए, हमें इसे सीधे ऐक्सेस करना होगा:
JavaScript
var db = firebase.database(); db.ref("records/rec1").once("value", function(snap) { // SUCCESS! }, function(err) { // error callback is not called });
Objective-C
FIRDatabaseReference *ref = [[FIRDatabase database] reference]; [[ref child:@"records/rec1"] observeSingleEventOfType:FEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) { // SUCCESS! }];
Swift
var ref = FIRDatabase.database().reference() ref.child("records/rec1").observeSingleEventOfType(.Value, withBlock: { snapshot in // SUCCESS! })
Java
FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference ref = database.getReference("records/rec1"); ref.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot snapshot) { // SUCCESS! } @Override public void onCancelled(FirebaseError firebaseError) { // error callback is not called } });
REST
curl https://docs-examples.firebaseio.com/rest/records/rec1 # SUCCESS!
जगह की जानकारी वाला वैरिएबल
Realtime Database Rules, पाथ सेगमेंट से मैच करने के लिए $location
वैरिएबल का इस्तेमाल करता है. अपने पाथ सेगमेंट के आगे $
प्रीफ़िक्स का इस्तेमाल करें, ताकि आपके नियम को पाथ के किसी भी चाइल्ड नोड से मैच किया जा सके.
{
"rules": {
"rooms": {
// This rule applies to any child of /rooms/, the key for each room id
// is stored inside $room_id variable for reference
"$room_id": {
"topic": {
// The room's topic can be changed if the room id has "public" in it
".write": "$room_id.contains('public')"
}
}
}
}
}
$variable
का इस्तेमाल, पाथ के नामों के साथ भी किया जा सकता है.
{
"rules": {
"widget": {
// a widget can have a title or color attribute
"title": { ".validate": true },
"color": { ".validate": true },
// but no other child paths are allowed
// in this case, $other means any key excluding "title" and "color"
"$other": { ".validate": false }
}
}
}