यह पेज सुरक्षा के नियमों को बनाने और सुरक्षा नियमों के लिए लिखने की शर्तों के सिद्धांतों पर जानकारी देता है, ताकि यह बताया जा सके कि Cloud Firestore के सुरक्षा नियम क्वेरी के साथ कैसे इंटरैक्ट करते हैं. इसमें इस बारे में बारीकी से बताया गया है कि सुरक्षा के नियम, उन क्वेरी पर कैसे असर डालते हैं जिन्हें लिखा जा सकता है. इसमें यह भी बताया गया है कि कैसे पक्का किया जाए कि आपकी क्वेरी में भी वही पाबंदियां लागू हों जो सुरक्षा के नियमों का पालन करती हैं. इस पेज पर, 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
फ़ील्ड सेव होते हैं. इन उदाहरणों में माना जाता है कि ऐप्लिकेशन, दस्तावेज़ बनाने वाले उपयोगकर्ता के यूआईडी में author
फ़ील्ड को सेट करने के लिए, Firebase से पुष्टि करने की सुविधा का इस्तेमाल करता है. Firebase से पुष्टि करने की सुविधा से, सुरक्षा नियमों में 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}
का इस्तेमाल करके, अपने कलेक्शन ग्रुप के लिए एक नियम लिखें.
उदाहरण के लिए, posts
सब-कलेक्शन वाले forum
दस्तावेज़ों में व्यवस्थित फ़ोरम देखें:
/फ़ोरम/{forumid}/पोस्ट/{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}
फ़ील्ड के आधार पर, सुरक्षित कलेक्शन ग्रुप क्वेरी
सिंगल-कलेक्शन क्वेरी की तरह, कलेक्शन ग्रुप क्वेरी भी आपके सुरक्षा नियमों की शर्तों के मुताबिक होनी चाहिए. उदाहरण के लिए, हम ऊपर दिए गए stories
उदाहरण की तरह, हर फ़ोरम पोस्ट में published
फ़ील्ड जोड़ सकते हैं:
/फ़ोरम/{forumid}/पोस्ट/{postid}
{
author: "some_auth_id",
authorname: "some_username",
content: "I just read a great story.",
published: false
}
इसके बाद, हम published
स्थिति और author
पोस्ट के आधार पर, posts
कलेक्शन ग्रुप के लिए नियम लिख सकते हैं:
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
}
}
}
अगले चरण
- भूमिका पर आधारित ऐक्सेस कंट्रोल के उदाहरण के लिए, उपयोगकर्ताओं और ग्रुप के लिए डेटा ऐक्सेस करना लेख पढ़ें.
- सुरक्षा नियमों से जुड़ा रेफ़रंस पढ़ें.