इस पेज पर,
Cloud Firestore Security Rules और क्वेरी के बीच इंटरैक्शन के बारे में बताया गया है. इसके लिए,
सुरक्षा के नियमों को स्ट्रक्चर करने और
सुरक्षा के नियमों के लिए शर्तें लिखने से जुड़े कॉन्सेप्ट का इस्तेमाल किया गया है. इसमें यह भी बताया गया है कि सुरक्षा के नियम, क्वेरी पर कैसे असर डालते हैं. साथ ही, यह भी बताया गया है कि क्वेरी में सुरक्षा के नियमों वाली पाबंदियां कैसे लागू की जाती हैं. इस पेज पर, सुरक्षा के नियम लिखने का तरीका भी बताया गया है. इनकी मदद से, limit और orderBy जैसी क्वेरी की प्रॉपर्टी के आधार पर, क्वेरी को अनुमति दी जा सकती है या अस्वीकार किया जा सकता है.
नियम, फ़िल्टर नहीं होते
दस्तावेज़ों को वापस पाने के लिए क्वेरी लिखते समय, ध्यान रखें कि सुरक्षा के नियम फ़िल्टर नहीं होते. क्वेरी के नतीजे, सभी दस्तावेज़ों के लिए होते हैं या किसी के लिए नहीं. आपका समय और संसाधन बचाने के लिए, Cloud Firestore संभावित नतीजों के सेट के हिसाब से क्वेरी का आकलन करता है, बजाय इसके कि आपकी सभी क्वेरी के लिए फ़ील्ड की असल वैल्यू का आकलन किया जाए. अगर किसी क्वेरी से ऐसे दस्तावेज़ मिल सकते हैं जिन्हें क्लाइंट के पास पढ़ने की अनुमति नहीं है, तो पूरा अनुरोध अस्वीकार कर दिया जाता है.
क्वेरी और सुरक्षा के नियम
नीचे दिए गए उदाहरणों से पता चलता है कि आपको अपनी क्वेरी, सुरक्षा के नियमों की पाबंदियों के हिसाब से लिखनी होंगी.
auth.uid के आधार पर दस्तावेज़ों को सुरक्षित करना और क्वेरी करना
यहां दिए गए उदाहरण में, सुरक्षा के नियम से सुरक्षित दस्तावेज़ों को वापस पाने के लिए क्वेरी लिखने का तरीका बताया गया है. मान लीजिए, किसी डेटाबेस में story दस्तावेज़ों का कलेक्शन है:
/stories/{storyid}
{
title: "A Great Story",
content: "Once upon a time...",
author: "some_auth_id",
published: false
}
title और content फ़ील्ड के अलावा, हर दस्तावेज़ में author और published फ़ील्ड भी सेव होते हैं. इनका इस्तेमाल, ऐक्सेस कंट्रोल के लिए किया जाता है. इन उदाहरणों में यह माना गया है
कि ऐप्लिकेशन, Firebase Authentication का इस्तेमाल करके, author फ़ील्ड
को उस उपयोगकर्ता के यूआईडी पर सेट करता है जिसने दस्तावेज़ बनाया है. Firebase
Authentication, सुरक्षा के नियमों में request.auth वैरिएबल भी भरता है.
सुरक्षा का यह नियम, request.auth और
resource.data वैरिएबल का इस्तेमाल करके, हर
story के लिए पढ़ने और लिखने के ऐक्सेस को उसके लेखक तक सीमित करता है:
service cloud.firestore {
match /databases/{database}/documents {
match /stories/{storyid} {
// Only the authenticated user who authored the document can read or write
allow read, write: if request.auth != null && request.auth.uid == resource.data.author;
}
}
}
मान लीजिए, आपके ऐप्लिकेशन में एक ऐसा पेज है जिस पर उपयोगकर्ता को, उसके लिखे गए story दस्तावेज़ों की सूची दिखती है. आपको लग सकता है कि इस पेज को भरने के लिए, इस क्वेरी का इस्तेमाल किया जा सकता है. हालांकि, यह क्वेरी काम नहीं करेगी, क्योंकि इसमें सुरक्षा के नियमों वाली पाबंदियां शामिल नहीं हैं:
अमान्य: क्वेरी की पाबंदियां, सुरक्षा के नियमों की पाबंदियों से मेल नहीं खातीं
// This query will fail
db.collection("stories").get()
क्वेरी तब भी काम नहीं करेगी, जब मौजूदा उपयोगकर्ता, हर story दस्तावेज़ का लेखक हो. ऐसा इसलिए होता है, क्योंकि जब
Cloud Firestore सुरक्षा के नियमों को लागू करता है, तो यह क्वेरी का आकलन आपके डेटाबेस में मौजूद दस्तावेज़ों की असल प्रॉपर्टी के बजाय, संभावित नतीजों के सेट के हिसाब से करता है. अगर किसी क्वेरी में संभावित तौर पर ऐसे दस्तावेज़ शामिल हो सकते हैं जो सुरक्षा के नियमों का उल्लंघन करते हैं, तो वह क्वेरी काम नहीं करेगी.
इसके उलट, यह क्वेरी काम करेगी, क्योंकि इसमें author फ़ील्ड पर वही पाबंदी लागू है जो सुरक्षा के नियमों में है:
मान्य: क्वेरी की पाबंदियां, सुरक्षा के नियमों की पाबंदियों से मेल खाती हैं
var user = firebase.auth().currentUser;
db.collection("stories").where("author", "==", user.uid).get()
किसी फ़ील्ड के आधार पर दस्तावेज़ों को सुरक्षित करना और क्वेरी करना
क्वेरी और नियमों के बीच इंटरैक्शन को और बेहतर तरीके से समझने के लिए, यहां दिए गए सुरक्षा के नियमों में stories कलेक्शन के लिए, पढ़ने के ऐक्सेस को बढ़ाया गया है. इससे कोई भी उपयोगकर्ता, story दस्तावेज़ पढ़ सकता है. इसके लिए, published फ़ील्ड को true पर सेट करना होगा.
service cloud.firestore {
match /databases/{database}/documents {
match /stories/{storyid} {
// Anyone can read a published story; only story authors can read unpublished stories
allow read: if resource.data.published == true || (request.auth != null && request.auth.uid == resource.data.author);
// Only story authors can write
allow write: if request.auth != null && request.auth.uid == resource.data.author;
}
}
}
पब्लिश किए गए पेजों के लिए क्वेरी में, सुरक्षा के नियमों वाली पाबंदियां शामिल होनी चाहिए:
db.collection("stories").where("published", "==", true).get()
क्वेरी की पाबंदी .where("published", "==", true) से यह पक्का होता है कि
resource.data.published की वैल्यू true हो. इसलिए, यह क्वेरी सुरक्षा के नियमों के मुताबिक है और इसे डेटा पढ़ने की अनुमति है.
OR क्वेरी
नियमों के सेट के हिसाब से, लॉजिकल OR क्वेरी (or, in, या array-contains-any)
का आकलन करते समय, Cloud Firestore हर तुलना वैल्यू
का आकलन अलग-अलग करता है. हर तुलना वैल्यू, सुरक्षा के नियम की पाबंदियों के मुताबिक होनी चाहिए. उदाहरण के लिए, इस नियम के लिए:
match /mydocuments/{doc} {
allow read: if resource.data.x > 5;
}
अमान्य: क्वेरी से यह पक्का नहीं होता कि सभी संभावित दस्तावेज़ों के लिए,
x > 5 हो
// These queries will fail
query(db.collection("mydocuments"),
or(where("x", "==", 1),
where("x", "==", 6)
)
)
query(db.collection("mydocuments"),
where("x", "in", [1, 3, 6, 42, 99])
)
मान्य: क्वेरी से यह पक्का होता है कि सभी संभावित दस्तावेज़ों के लिए,
x > 5 हो
query(db.collection("mydocuments"),
or(where("x", "==", 6),
where("x", "==", 42)
)
)
query(db.collection("mydocuments"),
where("x", "in", [6, 42, 99, 105, 200])
)
क्वेरी पर लागू पाबंदियों का आकलन करना
सुरक्षा के नियम, क्वेरी की पाबंदियों के आधार पर, उन्हें स्वीकार या अस्वीकार भी कर सकते हैं.
request.query वैरिएबल में, क्वेरी की limit, offset,
और orderBy प्रॉपर्टी शामिल होती हैं. उदाहरण के लिए, सुरक्षा के नियम, ऐसी किसी भी क्वेरी को अस्वीकार कर सकते हैं जिसमें वापस पाए जाने वाले दस्तावेज़ों की ज़्यादा से ज़्यादा संख्या को किसी तय रेंज तक सीमित नहीं किया गया हो:
allow list: if request.query.limit <= 10;
नियमों के इस सेट से पता चलता है कि क्वेरी पर लागू पाबंदियों का आकलन करने वाले सुरक्षा के नियम कैसे लिखे जाते हैं. इस उदाहरण में, stories के पिछले नियमों के सेट में ये बदलाव किए गए हैं:
- नियमों के सेट में, पढ़ने के नियम को
getऔरlistके नियमों में बांटा गया है. getका नियम, एक-एक दस्तावेज़ को वापस पाने की सुविधा को, सार्वजनिक दस्तावेज़ों या उपयोगकर्ता के लिखे गए दस्तावेज़ों तक सीमित करता है.listका नियम, क्वेरी के लिए भी वही पाबंदियां लागू करता है जोgetके नियम में हैं. यह क्वेरी की सीमा की भी जांच करता है. इसके बाद, बिना किसी सीमा वाली या 10 से ज़्यादा की सीमा वाली किसी भी क्वेरी को अस्वीकार कर देता है.- नियमों के सेट में, कोड को डुप्लीकेट होने से बचाने के लिए,
authorOrPublished()फ़ंक्शन तय किया गया है.
service cloud.firestore {
match /databases/{database}/documents {
match /stories/{storyid} {
// Returns `true` if the requested story is 'published'
// or the user authored the story
function authorOrPublished() {
return resource.data.published == true || request.auth.uid == resource.data.author;
}
// Deny any query not limited to 10 or fewer documents
// Anyone can query published stories
// Authors can query their unpublished stories
allow list: if request.query.limit <= 10 &&
authorOrPublished();
// Anyone can retrieve a published story
// Only a story's author can retrieve an unpublished story
allow get: if authorOrPublished();
// Only a story's author can write to a story
allow write: if request.auth.uid == resource.data.author;
}
}
}
कलेक्शन ग्रुप क्वेरी और सुरक्षा के नियम
डिफ़ॉल्ट रूप से, क्वेरी किसी एक कलेक्शन के दायरे में होती हैं. साथ ही, ये सिर्फ़ उसी कलेक्शन से नतीजे वापस पाती हैं. कलेक्शन ग्रुप क्वेरी की मदद से, एक ही आईडी वाले सभी कलेक्शन से नतीजे वापस पाए जा सकते हैं. इस सेक्शन में, सुरक्षा के नियमों का इस्तेमाल करके, कलेक्शन ग्रुप क्वेरी को सुरक्षित करने का तरीका बताया गया है.
कलेक्शन ग्रुप के आधार पर दस्तावेज़ों को सुरक्षित करना और क्वेरी करना
सुरक्षा के नियमों में, आपको कलेक्शन ग्रुप के लिए नियम लिखकर, कलेक्शन ग्रुप क्वेरी को साफ़ तौर पर अनुमति देनी होगी:
- पक्का करें कि
rules_version = '2';नियमों के सेट की पहली लाइन हो. कलेक्शन ग्रुप क्वेरी के लिए, सुरक्षा के नियमों के वर्शन 2 में मौजूद, वाइल्डकार्ड{name=**}के नए रिकर्सिव व्यवहार की ज़रूरत होती है. - अपने कलेक्शन ग्रुप के लिए नियम लिखें
match /{path=**}/[COLLECTION_ID]/{doc}.
उदाहरण के लिए, मान लीजिए कि कोई फ़ोरम, forum दस्तावेज़ों में व्यवस्थित है. इनमें posts सबकलेक्शन शामिल हैं:
/forums/{forumid}/posts/{postid}
{
author: "some_auth_id",
authorname: "some_username",
content: "I just read a great story.",
}
इस ऐप्लिकेशन में, हम पोस्ट के मालिकों को उनमें बदलाव करने की अनुमति देते हैं. साथ ही, पुष्टि किए गए उपयोगकर्ता, पोस्ट पढ़ सकते हैं:
service cloud.firestore {
match /databases/{database}/documents {
match /forums/{forumid}/posts/{post} {
// Only authenticated users can read
allow read: if request.auth != null;
// Only the post author can write
allow write: if request.auth != null && request.auth.uid == resource.data.author;
}
}
}
पुष्टि किया गया कोई भी उपयोगकर्ता, किसी भी फ़ोरम की पोस्ट वापस पा सकता है:
db.collection("forums/technology/posts").get()
हालांकि, अगर आपको मौजूदा उपयोगकर्ता को, सभी फ़ोरम पर उसकी पोस्ट दिखानी हैं, तो क्या करना होगा?
सभी posts कलेक्शन से नतीजे वापस पाने के लिए, कलेक्शन ग्रुप क्वेरी का इस्तेमाल करके
नतीजे वापस पाए जा सकते हैं:
var user = firebase.auth().currentUser;
db.collectionGroup("posts").where("author", "==", user.uid).get()
सुरक्षा के नियमों में, आपको posts कलेक्शन ग्रुप के लिए, पढ़ने या सूची बनाने का नियम लिखकर, इस क्वेरी को अनुमति देनी होगी:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Authenticated users can query the posts collection group
// Applies to collection queries, collection group queries, and
// single document retrievals
match /{path=**}/posts/{post} {
allow read: if request.auth != null;
}
match /forums/{forumid}/posts/{postid} {
// Only a post's author can write to a post
allow write: if request.auth != null && request.auth.uid == resource.data.author;
}
}
}
हालांकि, ध्यान दें कि ये नियम, क्रम के बावजूद, आईडी posts वाले सभी कलेक्शन पर लागू होंगे. उदाहरण के लिए, ये नियम, posts के इन सभी कलेक्शन पर लागू होते हैं:
/posts/{postid}/forums/{forumid}/posts/{postid}/forums/{forumid}/subforum/{subforumid}/posts/{postid}
किसी फ़ील्ड के आधार पर, कलेक्शन ग्रुप क्वेरी को सुरक्षित करना
एक कलेक्शन वाली क्वेरी की तरह, कलेक्शन ग्रुप क्वेरी को भी सुरक्षा के नियमों में सेट की गई पाबंदियों के मुताबिक होना चाहिए. उदाहरण के लिए, हम हर फ़ोरम पोस्ट में published फ़ील्ड जोड़ सकते हैं. जैसा कि हमने ऊपर दिए गए stories के उदाहरण में किया था:
/forums/{forumid}/posts/{postid}
{
author: "some_auth_id",
authorname: "some_username",
content: "I just read a great story.",
published: false
}
इसके बाद, हम posts कलेक्शन ग्रुप के लिए, published की स्थिति और पोस्ट के author के आधार पर नियम लिख सकते हैं:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Returns `true` if the requested post is 'published'
// or the user authored the post
function authorOrPublished() {
return resource.data.published == true || request.auth.uid == resource.data.author;
}
match /{path=**}/posts/{post} {
// Anyone can query published posts
// Authors can query their unpublished posts
allow list: if authorOrPublished();
// Anyone can retrieve a published post
// Authors can retrieve an unpublished post
allow get: if authorOrPublished();
}
match /forums/{forumid}/posts/{postid} {
// Only a post's author can write to a post
allow write: if request.auth.uid == resource.data.author;
}
}
}
इन नियमों के साथ, वेब, Apple, और Android क्लाइंट ये क्वेरी कर सकते हैं:
कोई भी व्यक्ति, किसी फ़ोरम में पब्लिश की गई पोस्ट वापस पा सकता है:
db.collection("forums/technology/posts").where('published', '==', true).get()कोई भी व्यक्ति, सभी फ़ोरम पर किसी लेखक की पब्लिश की गई पोस्ट वापस पा सकता है:
db.collectionGroup("posts").where("author", "==", "some_auth_id").where('published', '==', true).get()लेखक, सभी फ़ोरम पर अपनी पब्लिश और अनपब्लिश की गई सभी पोस्ट वापस पा सकते हैं:
var user = firebase.auth().currentUser; db.collectionGroup("posts").where("author", "==", user.uid).get()
कलेक्शन ग्रुप और दस्तावेज़ के पाथ के आधार पर दस्तावेज़ों को सुरक्षित करना और क्वेरी करना
कुछ मामलों में, आपको दस्तावेज़ के पाथ के आधार पर, कलेक्शन ग्रुप क्वेरी को सीमित करना पड़ सकता है. इन पाबंदियों को बनाने के लिए, फ़ील्ड के आधार पर दस्तावेज़ों को सुरक्षित करने और क्वेरी करने के लिए इस्तेमाल की जाने वाली तकनीकों का इस्तेमाल किया जा सकता है.
मान लीजिए, कोई ऐप्लिकेशन, कई स्टॉक और क्रिप्टोकरेंसी एक्सचेंज में हर उपयोगकर्ता के लेन-देन पर नज़र रखता है:
/users/{userid}/exchange/{exchangeid}/transactions/{transaction}
{
amount: 100,
exchange: 'some_exchange_name',
timestamp: April 1, 2019 at 12:00:00 PM UTC-7,
user: "some_auth_id",
}
user फ़ील्ड पर ध्यान दें. भले ही, हमें दस्तावेज़ के पाथ से पता हो कि transaction दस्तावेज़ का मालिक कौन है, लेकिन हम इस जानकारी को हर transaction दस्तावेज़ में डुप्लीकेट करते हैं. ऐसा इसलिए, क्योंकि इससे हमें दो काम करने में मदद मिलती है:
कलेक्शन ग्रुप क्वेरी लिखना. ये क्वेरी, दस्तावेज़ के पाथ में
/users/{userid}शामिल करने वाले दस्तावेज़ों तक सीमित होती हैं. उदाहरण के लिए:var user = firebase.auth().currentUser; // Return current user's last five transactions across all exchanges db.collectionGroup("transactions").where("user", "==", user).orderBy('timestamp').limit(5)transactionsकलेक्शन ग्रुप पर की जाने वाली सभी क्वेरी के लिए, इस पाबंदी को लागू करना. इससे कोई एक उपयोगकर्ता, दूसरे उपयोगकर्ता केtransactionदस्तावेज़ वापस नहीं पा सकता.
हम सुरक्षा के नियमों में इस पाबंदी को लागू करते हैं. साथ ही, user फ़ील्ड के लिए डेटा की पुष्टि भी शामिल करते हैं:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{path=**}/transactions/{transaction} {
// Authenticated users can retrieve only their own transactions
allow read: if resource.data.user == request.auth.uid;
}
match /users/{userid}/exchange/{exchangeid}/transactions/{transaction} {
// Authenticated users can write to their own transactions subcollections
// Writes must populate the user field with the correct auth id
allow write: if userid == request.auth.uid && request.data.user == request.auth.uid
}
}
}
अगले चरण
- भूमिका के आधार पर ऐक्सेस कंट्रोल के बारे में ज़्यादा जानकारी के लिए, डेटा ऐक्सेस को सुरक्षित करना उपयोगकर्ताओं और ग्रुप के लिए लेख पढ़ें.
- सुरक्षा के नियमों का रेफ़रंस पढ़ें.