Verileri güvenli bir şekilde sorgulama

Bu sayfa, proje yönetimi alanındaki Güvenlik Kurallarının Yapılandırılması Nasıl yapıldığını açıklamak için Güvenlik Kuralları İçin Koşullar Yazma Cloud Firestore Güvenlik Kuralları, sorgularla etkileşime girer. Bu, proje yöneticilerinin güvenlik kuralları, yazabileceğiniz sorguları etkiler ve sorgularınız güvenlik kurallarınızla aynı kısıtlamaları kullanır. Bu sayfa ayrıca Sorguya göre sorgulara izin vermek veya sorguları reddetmek için güvenlik kurallarının nasıl yazılacağını açıklar limit ve orderBy gibi mülkler.

Kurallar filtre değildir

Dokümanları almak için sorgu yazarken güvenlik kurallarının ya hiç ya hiç yoktur. Zamandan ve kaynaklardan tasarruf etmenizi sağlamak için Cloud Firestore, sorguyu potansiyel sonuç kümesine göre değerlendirir değerleri kullanabilirsiniz. Bir sorgu potansiyel olarak istemcinin okuma izni olmayan dokümanları döndürebilir, tüm istek başarısız olur.

Sorgular ve güvenlik kuralları

Aşağıdaki örneklerde gösterildiği gibi sorgularınızı kısıtlanmasını sağlayabilirsiniz.

auth.uid temelinde belgelerin güvenliğini sağlayın ve sorgulayın

Aşağıdaki örnekte, dokümanları almak için nasıl sorgu yazılacağı gösterilmektedir tarafından korunuyor. Şu bilgilerin bulunduğu bir veritabanını düşünün: story doküman:

/Hikayeler/{storyid}

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

title ve content alanlarına ek olarak her belgede Erişim denetimi için kullanılacak author ve published alanları Bu örneklerde, Uygulama, author alanını ayarlamak için Firebase Authentication'ı kullanıyor dokümanı oluşturan kullanıcının UID'sine gönderilir. Firebase Kimlik doğrulama,request.auth güvenlik kurallarını gözden geçireceğiz.

Aşağıdaki güvenlik kuralı, request.auth ve Her biri için okuma ve yazma erişimini kısıtlamak üzere resource.data değişkenleri Yazarı için 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;
    }
  }
}

Uygulamanızın, kullanıcıya story listesi gösteren bir sayfa içerdiğini varsayalım Google Dokümanlar ve Google Haritalar'ı kullanır. Bu gibi özelliklerden faydalanabilmek için sorgusunu kullanın. Ancak bu sorgu, olarak, güvenlik kurallarınızla aynı kısıtlamaları eklemeniz gerekir:

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

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

Geçerli kullanıcı gerçekten her dokümanın yazarı olsa bile sorgu başarısız olur. story doküman. Bu davranışın nedeni, Cloud Firestore, güvenlik kurallarınızı uygular ve sorguyu değerlendirir. potansiyel sonuç kümesine göre değil, inceleyebilirsiniz. Bir sorgu potansiyel olarak doküman içerebiliyor mu? sorgu başarısız olur.

Buna karşılık, aşağıdaki sorgu başarılı olur çünkü kısıtlamasını (güvenlik kuralları olarak author alanında) yapmanız gerekir:

Geçerli: Sorgu kısıtlamaları güvenlikle eşleşiyor kural kısıtlamaları

var user = firebase.auth().currentUser;

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

Bir alana göre belgelerin güvenliğini sağlayın ve sorgulayın

Sorgular ve kurallar arasındaki etkileşimi daha iyi göstermek için aşağıdaki kurallar, stories koleksiyonunun okuma erişimini genişleterek tüm kullanıcıların şunları yapmasına izin verir: published alanının true olarak ayarlandığı story dokümanlarını okuyabilirsiniz.

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 için yapılan sorgu, güvenlik kurallarınız:

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

.where("published", "==", true) sorgu kısıtlaması, Tüm sonuçlar için resource.data.published değeri true. Dolayısıyla bu sorgu web sitesi, güvenlik kurallarına uygun ve verileri okuma iznine sahip olmalıdır.

OR sorgu

Mantıksal bir OR sorgusu değerlendirirken (or, in veya array-contains-any) Bir kural kümesine göre Cloud Firestore her karşılaştırma değerini değerlendirir. ayrı olarak düzenleyebilirsiniz. Her karşılaştırma değeri, güvenlik kuralı kısıtlamalarını karşılamalıdır. Örneğin, Örneğin, şu kuralı kullanın:

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

Geçersiz: Sorgu, Tüm olası dokümanlar için 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])
    )

Geçerli: Sorgu, Tüm olası dokümanlar için 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])
    )

Sorgulardaki kısıtlamaları değerlendirme

Ayrıca güvenlik kurallarınız, kısıtlamalarına göre sorguları kabul edebilir veya reddedebilir. request.query değişkeni limit, offset, ve orderBy özelliği hakkında daha fazla bilgi edinin. Örneğin, güvenlik kurallarınız maksimum doküman sayısını sınırlamayan sorgular reddedebilir belirli bir aralığa alındı:

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

Aşağıdaki kural kümesi, kampanyalarınıza yönelik güvenlik kurallarının nasıl yazılacağını gösterir kısıtlamalara tabidir. Bu örnek, önceki stories kapsamını genişletir kural kümesini aşağıdaki değişikliklerle uyumlu hale getirmelisiniz:

  • Kural kümesi, okuma kuralını get ve list için kurallara ayırır.
  • get kuralı, tek dokümanın alınmasını herkese açık dokümanlarla veya Kullanıcının yazdığı dokümanlar.
  • list kuralı, sorgular için get ile aynı kısıtlamaları uygular. Google aynı zamanda sorgu sınırını da kontrol eder ve ardından, üst sınır 10'dan fazladır.
  • Kural kümesi, koddan kaçınmak için bir authorOrPublished() işlevi tanımlar yineleme.
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 koleksiyonun kapsamındadır ve sonuçları alır yalnızca ilgili koleksiyondan. Entegre koleksiyon grubu sorgularını kullanarak şu koleksiyona sahip tüm koleksiyonları içeren bir koleksiyon grubundan sonuçları getir: aynı kimlik. Bu bölümde, koleksiyon grubu sorgularınızın güvenliğini nasıl sağlayacağınız açıklanmaktadır. güvenlik kurallarından yararlanırsınız.

Koleksiyon gruplarına göre dokümanların güvenliğini sağlayın ve sorgulayın

Güvenlik kurallarınızda koleksiyon grubu için bir kural yazarak koleksiyon grubu sorguları:

  1. rules_version = '2'; değerinin, kural grubunuzun ilk satırı olduğundan emin olun. Koleksiyon grup sorguları için yeni yinelemeli joker karakter {name=**} güvenliği kuralları sürüm 2.
  2. Koleksiyon grubunuz için şununla bir kural oluşturun: match /{path=**}/[COLLECTION_ID]/{doc}

Örneğin, aşağıdakileri içeren forum dokümanlar halinde düzenlenmiş bir forum düşünün posts alt koleksiyon:

/forumlar/{forumid}/posts/{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 okunabilir hale getiririz kimliği doğrulanmış kullanıcılar:

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ğrulanan kullanıcılar herhangi bir forumun yayınlarını alabilir:

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

Peki, mevcut kullanıcıya yayınlarını tüm forumlarda göstermek isterseniz ne olur? Şu bilgileri almak için bir koleksiyon grubu sorgusu kullanabilirsiniz: posts koleksiyonun tamamından sonuç:

var user = firebase.auth().currentUser;

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

Güvenlik kurallarınızda, bu sorguya posts koleksiyon grubu için bir okuma veya liste kuralı yazıyor:

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, kimliği posts olan tüm koleksiyonlar için geçerli olacağını unutmayın. fark etmiyor. Örneğin, bu kurallar aşağıdakilerin tümü için geçerlidir: posts koleksiyon:

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

Alan bazında güvenli toplama grubu sorguları

Tek koleksiyonlu sorgularda olduğu gibi, koleksiyon grubu sorguları da tarafından belirlenen kısıtlamalara bağlıdır. Örneğin, bir published ekleyebiliriz alanını yukarıdaki stories örneğinde yaptığımız gibi her forum gönderisine ekleyin:

/forumlar/{forumid}/posts/{postid}

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

Daha sonra, şuna dayalı olarak posts toplama grubu için kurallar yazabiliriz: published durumu ve author yayını:

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

Web, Apple ve Android istemcileri bu kurallarla aşağıdaki sorguları yapabilir:

  • Herkes forumda paylaşılan yayınları alabilir:

    db.collection("forums/technology/posts").where('published', '==', true).get()
    
  • Herkes, tüm forumlarda bir yazarın yayınlanmış yayınlarını alabilir:

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

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

Koleksiyon grubuna ve belge yoluna göre dokümanların güvenliğini sağlayın ve sorgulayın

Bazı durumlarda koleksiyon grubu sorgularını tıklayın. Bu kısıtlamaları oluşturmak için, aynı teknikleri bir alana göre belgelerin güvenliğini sağlamak ve sorgulamak.

Her kullanıcının işlemlerini takip eden bir uygulama düşünün para birimi borsaları arasında ne kadar para kazanıyor?

/users/{userid}/exchange/{exchangeid}/transactions/{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. Hangi kullanıcının transaction sahibi olduğunu bilsek de bir doküman yolu olduğu için bu bilgileri her transaction dokümanı sayesinde iki şeyi yapabiliyoruz:

  • Şunları içeren dokümanlarla sınırlı koleksiyon grubu sorguları yazma: belge yolunda belirli bir /users/{userid}. Ö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)
    
  • Bu kısıtlamayı transactions koleksiyonundaki tüm sorgular için uygula gruplayarak bir kullanıcının başka bir kullanıcının transaction dokümanlarını alamaması sağlanır.

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

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