डेटा को सुरक्षित तरीके से क्वेरी करें

इस पेज पर, इन विषयों के बारे में जानकारी दी गई है सुरक्षा नियमों का स्ट्रक्चर बनाना और सुरक्षा नियमों के लिए लिखने की शर्तें, ताकि यह बताया जा सके कि 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 फ़ील्ड. ये उदाहरण 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;
    }

  }
}

कलेक्शन ग्रुप की क्वेरी और सुरक्षा के नियम

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

कलेक्शन ग्रुप के आधार पर, सुरक्षित और क्वेरी वाले दस्तावेज़

अपने सुरक्षा नियमों में, आपको साफ़ तौर पर इसकी अनुमति देनी होगी कलेक्शन ग्रुप की क्वेरी करने के लिए:

  1. पक्का करें कि आपके नियमों-सेट की पहली लाइन rules_version = '2'; है. डेटा इकट्ठा करना ग्रुप क्वेरी के लिए सुरक्षा का नया रिकर्सिव वाइल्डकार्ड {name=**} व्यवहार नियम वर्शन 2.
  2. match /{path=**}/[COLLECTION_ID]/{doc} का इस्तेमाल करके, अपने कलेक्शन ग्रुप के लिए कोई नियम लिखें.

उदाहरण के लिए, ऐसे forum दस्तावेज़ों में व्यवस्थित किए गए फ़ोरम पर विचार करें जिनमें ये शामिल हों posts उप-संग्रह:

/फ़ोरम/{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}

किसी फ़ील्ड के आधार पर, कलेक्शन ग्रुप की क्वेरी को सुरक्षित करना

सिंगल-कलेक्शन क्वेरी की तरह, कलेक्शन ग्रुप क्वेरी भी शर्तों के मुताबिक होनी चाहिए आपके सुरक्षा नियमों की ओर से सेट की गई कंस्ट्रेंट. उदाहरण के लिए, हम हर फ़ोरम पोस्ट में 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
    }
  }
}

अगले चरण