Google is committed to advancing racial equity for Black communities. See how.
Bu sayfa, Cloud Translation API ile çevrilmiştir.
Switch to English

Verileri güvenli bir şekilde sorgulayın

Bu sayfa, Cloud Firestore Güvenlik Kurallarının sorgularla nasıl etkileşime girdiğini açıklamak için Güvenlik Kurallarını Yapılandırma ve Güvenlik Kuralları için Yazma Koşulları konusundaki kavramlar üzerine kuruludur. Güvenlik kurallarının yazabileceğiniz sorguları nasıl etkilediğine daha yakından bakar ve sorgularınızın güvenlik kurallarınızla aynı kısıtlamaları nasıl kullanacağının nasıl sağlanacağını açıklar. Bu sayfa ayrıca limit ve orderBy gibi sorgu özelliklerine dayalı sorgulara izin vermek veya reddetmek için güvenlik kurallarının nasıl yazılacağını orderBy .

Kurallar filtre değildir

Belgeleri almak için sorgu yazarken, güvenlik kurallarının filtre olmadığını unutmayın; sorguların hepsi ya da hiçbir şey değildir. Zamandan ve kaynaklardan tasarruf etmek için Cloud Firestore, bir sorguyu tüm belgeleriniz için gerçek alan değerleri yerine potansiyel sonuç kümesine göre değerlendirir. Bir sorgu, istemcinin okuma iznine sahip olmadığı belgeleri geri gönderebilirse, tüm istek başarısız olur.

Sorgular ve güvenlik kuralları

Aşağıdaki örneklerde gösterildiği gibi, sorgularınızı güvenlik kurallarınızın kısıtlamalarına uyacak şekilde yazmalısınız.

Belgeleri auth.uid göre güvenli hale getirin ve sorgulayın

Aşağıdaki örnek, bir güvenlik kuralı tarafından korunan belgeleri almak için nasıl sorgu yazılacağını gösterir. story belgelerinin bir koleksiyonunu içeren bir veritabanı düşünün:

/ hikayeleri / {storyid}

 {
  title: "A Great Story",
  content: "Once upon a time...",
  author: "some_auth_id",
  published: false
}
 

title ve content alanlarına ek olarak, her belge author ve published alanları erişim kontrolü için kullanmak üzere saklar. Bu örnekler, uygulamanın author alanını belgeyi oluşturan kullanıcının UID'sine ayarlamak için Firebase Kimlik Doğrulaması'nı kullandığını varsayar. Firebase Kimlik Doğrulaması ayrıca güvenlik kurallarında request.auth değişkenini doldurur.

Aşağıdaki güvenlik kuralı, her bir story okuma ve yazma erişimini yazarına kısıtlamak için request.auth ve resource.data değişkenlerini kullanır:

 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;
    }
  }
}
 

Uygulamanızda, kullanıcıya yazdıkları story belgelerinin bir listesini gösteren bir sayfa içerdiğini varsayalım. Bu sayfayı doldurmak için aşağıdaki sorguyu kullanabilirsiniz. Ancak, güvenlik kurallarınızla aynı kısıtlamaları içermediğinden bu sorgu başarısız olur:

Geçersiz : Sorgu kısıtlamaları güvenlik kuralları kısıtlamalarıyla eşleşmiyor

 // This query will fail
db.collection("stories").get()
 

Mevcut kullanıcı aslında her story belgesinin yazarı olsa bile sorgu başarısız olur. Bu davranışın nedeni, Cloud Firestore güvenlik kurallarınızı uyguladığında, sorguyu veritabanınızdaki belgelerin gerçek özelliklerine göre değil, potansiyel sonuç kümesine göre değerlendirmesidir. Bir sorgu potansiyel olarak güvenlik kurallarınızı ihlal eden belgeler içerebilirse, sorgu başarısız olur.

Buna karşılık, author alanında güvenlik kuralları ile aynı kısıtlamayı içerdiğinden, aşağıdaki sorgu başarılı olur:

Geçerli : Sorgu kısıtlamaları, güvenlik kuralları kısıtlamalarıyla eşleşir

 var user = firebase.auth().currentUser;

db.collection("stories").where("author", "==", user.uid).get()
 

Belgeleri bir alana göre güvenli hale getirin ve sorgulayın

Ayrıca sorularınız ve kurallar arasındaki etkileşimi göstermek için, güvenlik kuralları aşağıda için okuma erişimi genişletmek stories okumak için herhangi bir kullanıcıya izin vermek için koleksiyon story belgeleri published alan olarak ayarlanır 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;
    }
  }
}
 

Yayınlanan sayfaların sorgusu, güvenlik kurallarıyla aynı kısıtlamaları içermelidir:

 db.collection("stories").where("published", "==", true).get()
 

.where("published", "==", true) sorgu kısıtı, resource.data.published herhangi bir sonuç için true olduğunu garanti eder. Bu nedenle, bu sorgu güvenlik kurallarını karşılar ve verileri okumalarına izin verilir.

in ve array-contains-any sorgularda

Bir değerlendirirken in ya da array-contains-any bir kural kümesi karşı sorgu madde, bulut Firestore ayrı ayrı karşılaştırma değeri değerlendirir. Her karşılaştırma değeri güvenlik kuralı kısıtlamalarını karşılamalıdır. Örneğin, aşağıdaki kural için:

 match /mydocuments/{doc} {
  allow read: if resource.data.x > 5;
}
 

Geçersiz : Sorgu, tüm olası belgeler için x > 5 olduğunu garanti etmez

 // This query will fail
db.collection("mydocuments").where("x", "in", [1, 3, 6, 42, 99]).get()
 

Geçerli : Sorgu, tüm olası belgeler için x > 5 olduğunu garanti eder

 db.collection("mydocuments").where("x", "in", [6, 42, 99, 105, 200]).get()
 

Sorgular üzerindeki kısıtlamaları değerlendirme

Güvenlik kurallarınız, kısıtlamalarına göre sorguları kabul edebilir veya reddedebilir. request.query değişkeni, bir sorgunun limit , offset ve orderBy özelliklerini içerir. Örneğin, güvenlik kurallarınız belirli bir aralıkla alınan maksimum belge sayısını sınırlamayan herhangi bir sorguyu reddedebilir:

 allow list: if request.query.limit <= 10;
 

Aşağıdaki kural kümesi, sorgulara getirilen kısıtlamaları değerlendiren güvenlik kurallarının nasıl yazılacağını gösterir. Bu örnek, önceki stories kural kümesini aşağıdaki değişikliklerle genişletir:

  • Kuralkümesi kuralları içine okuma kuralı ayıran get ve list .
  • get kural kısıtlar kullanıcının yazdığı kamu belgeler veya belgelere tek belgelerin erişilmesi.
  • list kuralı, get aynı kısıtlamaları uygular ancak sorgular için. Ayrıca sorgu sınırını kontrol eder, ardından sınırı olmayan veya sınırı 10'dan büyük olan sorguları reddeder.
  • authorOrPublished() kod çoğaltmasını önlemek için bir authorOrPublished() işlevini tanımlar.
 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;
    }

  }
}
 

Koleksiyon grubu sorguları ve güvenlik kuralları

Varsayılan olarak, sorgular tek bir koleksiyona dahil edilir ve sonuçları yalnızca bu koleksiyondan alır. Koleksiyon grubu sorgularıyla , sonuçları aynı kimliğe sahip tüm koleksiyonlardan oluşan bir koleksiyon grubundan alabilirsiniz. Bu bölümde, güvenlik grubu kullanarak toplama grubu sorgularınızın nasıl güvenli hale getirileceği açıklanmaktadır.

Belgeleri toplama gruplarına göre güvenli hale getirin ve sorgulayın

Güvenlik kurallarınızda, koleksiyon grubu için bir kural yazarak koleksiyon grubu sorgularına açıkça izin vermelisiniz:

  1. rules_version = '2'; olduğundan emin olun rules_version = '2'; kural kümenizin ilk satırıdır. Koleksiyon grubu sorguları, güvenlik kuralları sürüm 2'nin yeni özyinelemeli joker karakteri {name=**} gerektirir.
  2. Koleksiyon grubunuz için match /{path=**}/ [COLLECTION_ID] /{doc} kullanarak bir kural yazın.

Örneğin, posts alt koleksiyonlarını içeren forum belgelerinde düzenlenmiş bir forumu düşünün:

/ forumlar / {forumid} / mesaj / {postid}

 {
  author: "some_auth_id",
  authorname: "some_username",
  content: "I just read a great story.",
}
 

Bu uygulamada, yayınları sahipleri tarafından düzenlenebilir ve kimliği doğrulanmış kullanıcılar tarafından okunabilir hale getiririz:

 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;
    }
  }
}
 

Kimliği doğrulanmış herhangi bir kullanıcı, herhangi bir forumun gönderilerini alabilir:

 db.collection("forums/technology/posts").get()
 

Ancak mevcut kullanıcıya yayınlarını tüm forumlarda göstermek istiyorsanız ne olur? Tüm posts koleksiyonlarından sonuç almak için bir koleksiyon grubu sorgusu kullanabilirsiniz:

 var user = firebase.auth().currentUser;

db.collectionGroup("posts").where("author", "==", user.uid).get()
 

Güvenlik kurallarınızda, posts toplama grubu için bir okuma veya liste kuralı yazarak bu sorguya izin vermelisiniz:

 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;

    }
  }
}
 

Ancak, bu kuralların hiyerarşiden bağımsız olarak kimlik posts sahip tüm koleksiyonlar için geçerli olacağını unutmayın. Örneğin, bu kurallar aşağıdaki posts koleksiyonlarının tümüne uygulanır:

  • /posts/{postid}
  • /forums/{forumid}/posts/{postid}
  • /forums/{forumid}/subforum/{subforumid}/posts/{postid}

Bir alana dayalı güvenli toplama grubu sorguları

Tek koleksiyon sorguları gibi, koleksiyon grubu sorguları da güvenlik kurallarınız tarafından belirlenen kısıtlamaları karşılamalıdır. Örneğin, her bir forum yayınına yukarıdaki stories örneğinde yaptığımız gibi published alan ekleyebiliriz:

/ forumlar / {forumid} / mesaj / {postid}

 {
  author: "some_auth_id",
  authorname: "some_username",
  content: "I just read a great story.",
  published: false
}
 

Sonra kurallarını yazabilir posts dayalı toplama grubuna published durumu ve sonrası 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;
    }
  }
}
 

Bu kurallarla web, iOS ve Android istemcileri aşağıdaki sorguları yapabilir:

  • Bir forumda yayınlanan yayınları herkes alabilir:

     db.collection("forums/technology/posts").where('published', '==', true).get()
     
  • Tüm forumlarda yazarın yayınladığı yayınları herkes alabilir:

     db.collectionGroup("posts").where("author", "==", "some_auth_id").where('published', '==', true).get()
     
  • Yazarlar yayınlanmış ve yayınlanmamış tüm yayınlarını tüm forumlarda alabilir:

     var user = firebase.auth().currentUser;
    
    db.collectionGroup("posts").where("author", "==", user.uid).get()
     

Toplama grubu ve belge yoluna göre belgeleri güvenceye alın ve sorgulayın

Bazı durumlarda, toplama grubu sorgularını belge yoluna göre kısıtlamak isteyebilirsiniz. Bu kısıtlamaları oluşturmak için, bir alana dayalı belgeleri güvenceye almak ve sorgulamak için aynı teknikleri kullanabilirsiniz.

Birkaç hisse senedi ve kripto para birimi borsaları arasında her kullanıcının işlemlerini takip eden bir uygulamayı düşünün:

/ Kullanıcılar / {kimliği} / değişimi / {exchangeid} / işlemler / {işlem}

 {
  amount: 100,
  exchange: 'some_exchange_name',
  timestamp: April 1, 2019 at 12:00:00 PM UTC-7,
  user: "some_auth_id",
}
 

user alanına dikkat edin. Belgenin yolundan hangi kullanıcının bir transaction belgesine sahip olduğunu bilsek de, iki transaction yapmamıza izin verdiği için bu bilgileri her transaction belgesinde çoğaltırız:

  • Belge yollarında belirli bir /users/{userid} içeren belgelerle sınırlı koleksiyon grubu sorguları yazın. Örneğin:

     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)
     
  • Bir kullanıcının başka bir kullanıcının transaction belgelerini alamaması için bu kısıtlamayı transactions toplama grubundaki tüm sorgular için uygulayın.

Bu kısıtlamayı güvenlik kurallarımızda uyguluyoruz ve user alanı için veri doğrulaması ekliyoruz:

 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
    }
  }
}
 

Sonraki adımlar