Verileri güvenli bir şekilde sorgulama

Bu sayfada, Güvenlik Kurallarını Yapılandırma ve Güvenlik Kuralları İçin Koşullar Yazma bölümlerindeki kavramlar temel alınarak Cloud Firestore Security Rules ile sorguların nasıl etkileşime girdiği açıklanmaktadır. Güvenlik kurallarının yazabileceğiniz sorguları nasıl etkilediğini daha yakından 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 ayrıca, limit ve orderBy gibi sorgu özelliklerine göre sorgulara izin veren veya sorguları reddeden 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 temsilcinize (ör. Android Studio'da Gemini, Antigravity, Claude Code, Codex ve Cursor) kopyalayın. İstemi özelleştirebilir ve temsilcinizle birlikte üzerinde çalışabilirsiniz. Ayrıntılı kurulum 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ı, sorguların ya tamamen çalıştığını ya da hiç çalışmadığını unutmayın. Kurallar, zaman ve kaynak tasarrufu sağlamak için sorguyu tüm dokümanlarınızın gerçek alan değerleri yerine potansiyel sonuç kümesine göre değerlendirir. Bir sorgu, istemcinin okuma izni olmayan belgeler döndürebiliyorsa 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'e göre belgelerin güvenliğini sağlama ve belgeleri sorgulama

Aşağıdaki örnekte, bir güvenlik kuralıyla korunan belgeleri almak için nasıl sorgu yazılacağı gösterilmektedir. story doküman 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 depolanır. Bu örneklerde, uygulamanın author alanını dokümanı oluşturan kullanıcının UID'sine 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 story için okuma ve yazma erişimini yazarıyla kısıtlamak üzere 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ının yazdığı story dokümanların 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()

Mevcut kullanıcı her story dokümanının yazarı olsa bile sorgu başarısız olur. Bu davranışın nedeni, Kurallar'ın güvenlik kurallarınızı uygularken sorguyu veritabanınızdaki belgelerin gerçek özelliklerine göre değil, potansiyel sonuç kümesine göre değerlendirmesidir. Bir sorgu, güvenlik kurallarınızı ihlal eden dokümanları potansiyel olarak içerebiliyorsa sorgu başarısız olur.

Buna karşılık, aşağıdaki sorgu başarılı olur çünkü güvenlik kurallarıyla aynı author alanı kısıtlamasını 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üvence altına alma ve sorgulama

Sorgular ve kurallar arasındaki etkileşimi daha ayrıntılı bir şekilde göstermek için aşağıdaki güvenlik kuralları, stories koleksiyonu için okuma erişimini genişleterek tüm kullanıcıların published alanının true olarak ayarlandığı story belgelerini okumasına olanak tanır.

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 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ına uygundur ve verileri okumasına izin verilir.

OR sorgu

Mantıksal bir OR sorgusunu (or, in veya array-contains-any) bir kural grubuna göre değerlendirirken 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, tüm potansiyel dokümanlar için x > 5 garantisi vermiyor.

// 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 potansiyel belgeler için x > 5 değerini 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])
    )

Sorgulardaki 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, alınan maksimum belge 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 örnek, önceki stories kural grubunu aşağıdaki değişikliklerle genişletir:

  • Kural grubu, okuma kuralını get ve list için kurallara ayırır.
  • get kuralı, tek dokümanların alınmasını herkese açık dokümanlar veya kullanıcının yazdığı dokümanlarla kısıtlar.
  • list kuralı, get ile aynı kısıtlamaları uygular ancak sorgular için geçerlidir. Ayrıca sorgu sınırını kontrol eder ve sınırı olmayan veya sınırı 10'dan büyük olan tüm sorguları reddeder.
  • Kural kümesi, kodun kopyalanmasını önlemek için bir authorOrPublished() işlevi 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ırlıdır ve yalnızca o koleksiyondan sonuç alır. Koleksiyon grubu sorgularıyla, aynı kimliğe sahip tüm koleksiyonlardan oluşan bir koleksiyon grubundan sonuçlar alabilirsiniz. Bu bölümde, güvenlik kurallarını kullanarak koleksiyon grubu sorgularınızın güvenliğini nasıl sağlayacağınız açıklanmaktadır.

Koleksiyon gruplarına göre belgelerin güvenliğini sağlama ve belgeleri 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'; ifadesinin kural grubunuzun ilk satırı olduğundan emin olun. Koleksiyon grubu sorguları, güvenlik kuralları 2. sürümünün yeni özyinelemeli joker karakter {name=**} davranışını gerektirir.
  2. match /{path=**}/[COLLECTION_ID]/{doc} kullanarak koleksiyon grubunuz için bir kural yazın.

Örneğin, posts alt koleksiyonlarını içeren forum 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, yayınları sahipleri tarafından düzenlenebilir ve kimliği doğrulanmış kullanıcılar tarafından okunabilir hale getiriyoruz:

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, tek bir forumun yayınlarını alabilir:

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

Peki, mevcut kullanıcıya tüm forumlardaki yayınlarını göstermek isterseniz ne yapabilirsiniz? Tüm posts koleksiyonlarından 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 listeleme 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 kimliğine sahip 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 dayalı koleksiyon grubu sorgularının güvenliğini sağlama

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

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

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

Ardından, published durumuna ve yayın author değerine göre posts koleksiyon grubu için 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 kurallarla 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 forumlarda yayınlanan gönderilerini alabilir:

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

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

Koleksiyon grubuna ve belge yoluna göre belgelerin güvenliğini sağlama ve belgeleri sorgulama

Bazı durumlarda, koleksiyon grubu sorgularını doküman yoluna göre kısıtlamak isteyebilirsiniz. Bu kısıtlamaları oluşturmak için, dokümanların güvenliğini sağlamak ve dokümanları bir alana göre sorgulamak için kullandığınız teknikleri kullanabilirsiniz.

Her kullanıcının çeşitli hisse senedi ve kripto para borsalarındaki işlemlerini takip eden bir uygulama düşünün:

/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 dokümanının hangi kullanıcıya ait olduğunu dokümanın yolundan bilsek de bu bilgiyi her transaction dokümanında kopyalarız. Bu sayede iki şey yapabiliriz:

  • Doküman yolunda belirli bir /users/{userid} içeren dokümanlarla kısıtlanmış 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 dokümanlarını alamaması için bu kısıtlamayı transactions koleksiyon grubundaki tüm sorgulara uygulayın.

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

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