Verileri güvenli bir şekilde sorgulama

Bu sayfada, Güvenlik Kurallarını Yapılandırma ve Güvenlik Kuralları İçin Koşullar Yazma sayfalarındaki kavramlardan yararlanarak Cloud Firestore Security Rules öğesinin sorgularla nasıl etkileşime girdiği açıklanmaktadır. Güvenlik kurallarının yazabileceğiniz sorguları nasıl etkilediğini daha ayrıntılı bir şekilde inceler ve sorgularınızın güvenlik kurallarınızla aynı kısıtlamaları kullandığından nasıl emin olacağınızı açıklar. Bu sayfada, sorguları limit ve orderBy gibi sorgu özelliklerine göre izin verecek veya reddedecek şekilde güvenlik kurallarının nasıl yazılacağı da açıklanmaktadır.

Yapay zeka desteği için aşağıdaki istemi yapay zeka kodlama aracınıza (Android Studio'daki Gemini, Antigravity, Claude Code, Codex ve Cursor gibi) kopyalayın. İstemi özelleştirebilir ve temsilcinizle birlikte yineleme yapabilirsiniz. Ayrıntılı yükleme bilgileri için Firebase aracı becerileri sayfasını ziyaret edin.

Help me use Firebase in my app.
1. Make sure that **Firebase agent skills** are installed and updated. For Claude Code, Codex, or Cursor agents, help me install the Firebase plugin. For other agents, run `npx skills add firebase/agent-skills`. Always try to use **Firebase agent skills** for Firebase-related tasks.
2. Help me write, validate, and deploy Firebase Security Rules to protect my app's Firestore data.

Kurallar filtre değildir

Belgeleri almak için sorgu yazarken güvenlik kurallarının filtre olmadığını unutmayın. Sorgular ya tamamen ya da hiç çalışır. Kurallar, zamandan ve kaynaklardan tasarruf etmenizi sağlamak için bir sorguyu tüm dokümanlarınızın gerçek alan değerleri yerine olası sonuç kümesine göre değerlendirir. Bir sorgu, istemcinin okuma izni olmayan belgeleri döndürebilecekse isteğin tamamı 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 yazmanız gerekir.

auth.uid temelinde dokümanları güvenli hale getirme ve sorgulama

Aşağıdaki örnekte, bir güvenlik kuralıyla korunan dokümanları almak için sorgunun nasıl yazılacağı gösterilmektedir. story doküman koleksiyonu içeren bir veritabanı düşünün:

/stories/{storyid}

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

title ve content alanlarına ek olarak, her dokümanda erişim denetimi için kullanılacak author ve published alanları da saklanır. Bu örneklerde, uygulamanın author alanını belgeyi oluşturan kullanıcının UID'si olarak ayarlamak için Firebase Authentication kullandığı varsayılır. Firebase Authentication, güvenlik kurallarındaki request.auth değişkenini de doldurur.

Aşağıdaki güvenlik kuralı, her request.auth için okuma ve yazma erişimini yazarıyla kısıtlamak üzere resource.data ve story 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ığı story belgelerin listesini gösteren bir sayfa olduğunu varsayalım. Bu sayfayı doldurmak için aşağıdaki sorguyu kullanabileceğinizi düşünebilirsiniz. Ancak bu sorgu, güvenlik kurallarınızla aynı kısıtlamaları içermediği için 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()

Sorgu, mevcut kullanıcı aslında her story belgenin yazarı olsa bile başarısız olur. Bu davranışın nedeni, kurallar güvenlik kurallarınızı uygularken sorguyu veritabanınızdaki dokümanların gerçek özelliklerine göre değil, olası sonuç kümesine göre değerlendirmesidir. Bir sorgu, güvenlik kurallarınızı ihlal eden belgeler içerebilecekse sorgu başarısız olur.

Buna karşılık, aşağıdaki sorgu başarılı olur. Çünkü author alanında güvenlik kurallarıyla aynı kısıtlamayı içerir:

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

var user = firebase.auth().currentUser;

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

Belgeleri bir alana göre güvenli hale getirme ve sorgulama

Sorgular ve kurallar arasındaki etkileşimi daha iyi göstermek için aşağıdaki güvenlik kuralları, stories koleksiyonu için okuma erişimini genişleterek published alanı true olarak ayarlanmış story belgelerinin herhangi bir kullanıcı tarafından okunmasına izin verir.

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ınlanmış sayfalarla ilgili sorgu, güvenlik kurallarıyla aynı kısıtlamaları içermelidir:

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

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

OR sorgu

Bir kural grubuyla karşılaştırılan mantıksal bir OR sorgu (or, in veya array-contains-any) değerlendirilirken Kurallar, her karşılaştırma değerini ayrı ayrı 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, olası tüm belgeler için x > 5 özelliğini garanti etmez.

// 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, x > 5 için tüm olası belgeleri garanti eder.

query(db.collection("mydocuments"),
      or(where("x", "==", 6),
         where("x", "==", 42)
      )
    )

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

Sorgularla ilgili kısıtlamaları değerlendirme

Güvenlik kurallarınız, sorguları kısıtlamalarına göre 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, alınan dokümanların maksimum sayısını belirli bir aralıkla sınırlamayan tüm sorguları reddedebilir:

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

Aşağıdaki kural grubu, sorgulara uygulanan kısıtlamaları değerlendiren güvenlik kurallarının nasıl yazılacağını gösterir. Bu örnekte, önceki stories kural grubu aşağıdaki değişikliklerle genişletilmiştir:

  • Kural grubu, okuma kuralını get ve list için kurallara ayırır.
  • get kuralı, tek dokümanların alınmasını ortak dokümanlarla veya kullanıcının oluşturduğu dokümanlarla kısıtlar.
  • list kuralı, get ile aynı kısıtlamaları sorgular için uygular. Ayrıca sorgu sınırını da kontrol eder ve sınır içermeyen veya 10'dan büyük bir sınıra sahip sorguları reddeder.
  • Kural grubu, kod tekrarını önlemek için 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 koleksiyonla sınırlandırılır ve yalnızca bu koleksiyondan sonuç alınır. Koleksiyon grubu sorgularıyla, aynı kimliğe sahip tüm koleksiyonlardan oluşan bir koleksiyon grubundan sonuç alabilirsiniz. Bu bölümde, güvenlik kurallarını kullanarak koleksiyon grubu sorgularınızın nasıl güvenli hale getirileceği açıklanmaktadır.

Koleksiyon gruplarına göre dokümanları güvenli hale getirme ve sorgulama

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

  1. rules_version = '2';, kural setinizin ilk satırı olmalıdır. Collection group sorguları için güvenlik kuralları sürüm 2'nin yeni yinelemeli joker karakter {name=**} davranışı gerekir.
  2. match /{path=**}/[COLLECTION_ID]/{doc} kullanarak koleksiyon grubunuz için bir kural yazın.

Örneğin, forum alt koleksiyonlarını içeren posts dokümanlar halinde düzenlenmiş bir forumu ele alalım:

/forums/{forumid}/posts/{postid}

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

Bu uygulamada, gönderilerin sahipleri tarafından düzenlenebilmesini ve kimliği doğrulanmış kullanıcılar tarafından okunabilmesini sağlıyoruz:

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ış tüm kullanıcılar, herhangi bir forumun yayınlarını alabilir:

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

Ancak mevcut kullanıcıya tüm forumlardaki yayınlarını göstermek isterseniz ne yapmanız gerekir? posts koleksiyonun tümünden sonuç almak için koleksiyon grubu sorgusu kullanabilirsiniz:

var user = firebase.auth().currentUser;

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

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

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

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

Bir alana göre güvenli koleksiyon grubu sorguları

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

/forums/{forumid}/posts/{postid}

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

Daha sonra, posts koleksiyon grubu için published durumuna ve gönderi author göre kurallar yazabiliriz:

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 kurallar sayesinde Web, Apple ve Android istemcileri aşağıdaki sorguları yapabilir:

  • Herkes forumda yayınlanan gönderileri alabilir:

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

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

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

Koleksiyon grubuna ve doküman yoluna göre dokümanları güvenli hale getirme ve sorgulama

Bazı durumlarda, doküman yoluna göre koleksiyon grubu sorgularını kısıtlamak isteyebilirsiniz. Bu kısıtlamaları oluşturmak için, alan tabanlı belge güvenliği ve sorgulama ile ilgili aynı teknikleri kullanabilirsiniz.

Çeşitli borsa ve kripto para borsalarındaki her kullanıcının işlemlerini takip eden bir uygulamayı ele alalım:

/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 alanına dikkat edin. Bir transaction belgenin yolundan hangi kullanıcının sahibi olduğunu bilsek de bu bilgiyi her transaction belgede yineleriz. Çünkü bu sayede iki şey yapabiliriz:

  • Belge yolunda 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)
    
  • transactions koleksiyon grubundaki tüm sorgular için bu kısıtlamayı zorunlu kılın. Böylece bir kullanıcı, başka bir kullanıcının transaction belgelerini alamaz.

Bu kısıtlamayı güvenlik kurallarımızda uygularız ve user alanı için veri doğrulamayı dahil ederiz:

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