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 Koşullar Yazma bölümlerindeki kavramlara dayanmaktadır. 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ı kullanmasını nasıl sağlayacağınızı açıklar. Bu sayfada ayrıca, limit
ve orderBy
gibi sorgu özelliklerine dayalı olarak sorgulara izin vermek veya reddetmek için güvenlik kurallarının nasıl yazılacağı açıklanır.
Kurallar filtre değildir
Belgeleri almak için sorgular yazarken, güvenlik kurallarının filtreler olmadığını unutmayın; sorgular ya hep ya hiçtir. Cloud Firestore, size zaman ve kaynak tasarrufu sağlamak için bir sorguyu tüm belgeleriniz için gerçek alan değerleri yerine potansiyel sonuç kümesine göre değerlendirir. Bir sorgu potansiyel olarak müşterinin okuma iznine sahip olmadığı belgeleri döndürebilirse, isteğin tamamı başarısız olur.
Sorgular ve güvenlik kuralları
Aşağıdaki örneklerin gösterdiği gibi, sorgularınızı güvenlik kurallarınızın kısıtlamalarına uyacak şekilde yazmalısınız.
Belgeleri auth.uid
tabanlı olarak 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:
/hikayeler/{hikaye kimliği}
{
title: "A Great Story",
content: "Once upon a time...",
author: "some_auth_id",
published: false
}
title
ve content
alanlarına ek olarak, her belge erişim kontrolü için kullanmak üzere author
ve published
alanları saklar. Bu örnekler, uygulamanın, author
alanını belgeyi oluşturan kullanıcının UID'sine ayarlamak için Firebase Kimlik Doğrulaması kullandığını varsayar. Firebase Authentication, güvenlik kurallarındaki request.auth
değişkenini de doldurur.
Aşağıdaki güvenlik kuralı, yazarına her story
için okuma ve yazma erişimini 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ızın, kullanıcıya yazdığı story
belgelerinin listesini gösteren bir sayfa içerdiğini varsayalım. Bu sayfayı doldurmak için aşağıdaki sorguyu kullanabileceğinizi bekleyebilirsiniz. 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()
Geçerli kullanıcı aslında her story
belgesinin yazarı olsa bile sorgu başarısız olur. Bu davranışın nedeni, Cloud Firestore'un güvenlik kurallarınızı uyguladığında, sorguyu veritabanınızdaki belgelerin gerçek özelliklerine göre değil, olası sonuç kümesine göre değerlendirmesidir. Bir sorgu potansiyel olarak güvenlik kurallarınızı ihlal eden belgeler içeriyorsa 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 getirin ve sorgulayın
Sorgular ve kurallar arasındaki etkileşimi daha fazla göstermek için, aşağıdaki güvenlik kuralları, stories
koleksiyonu için okuma erişimini genişleterek, herhangi bir kullanıcının, published
alanının true
olarak ayarlandığı durumlarda story
belgelerini okuması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ı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ı, her sonuç için resource.data.published
true
olduğunu garanti eder. Bu nedenle, bu sorgu güvenlik kurallarını karşılar ve verileri okumasına izin verilir.
OR
sorguları
Mantıksal OR
sorgusunu ( or
, in
veya array-contains-any
) bir kural kümesine göre değerlendirirken, Cloud Firestore her bir 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 olası belgeler için x > 5
olduğunu 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, tüm olası belgeler için x > 5
olduğunu 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 ayrıca 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 herhangi bir sorguyu reddedebilir:
allow list: if request.query.limit <= 10;
Aşağıdaki kural seti, sorgulara yerleştirilen kısıtlamaları değerlendiren güvenlik kurallarının nasıl yazılacağını gösterir. Bu örnek, önceki stories
kural setini aşağıdaki değişikliklerle genişletir:
- Kural kümesi, okuma kuralını
get
velist
için kurallara ayırır. -
get
kuralı, tek belgelerin alınmasını genel belgeler veya kullanıcının yazdığı belgelerle sınırlar. -
list
kuralı, sorgular dışındaget
ile aynı kısıtlamaları uygular. Ayrıca sorgu limitini de kontrol eder, ardından limitsiz veya 10'dan büyük limitli sorguları reddeder. - Kural kümesi, kod tekrarı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 koleksiyonun kapsamına alınır ve sonuçları yalnızca bu koleksiyondan alır. Koleksiyon grubu sorguları ile, aynı kimliğe sahip tüm koleksiyonlardan oluşan bir koleksiyon grubundan sonuçlar alabilirsiniz. Bu bölümde, güvenlik kurallarını kullanarak toplama grubu sorgularınızın güvenliğini nasıl sağlayacağınız açıklanmaktadır.
Belgeleri toplama gruplarına göre güvenli hale getirin ve sorgulayın
Güvenlik kurallarınızda, toplama grubu için bir kural yazarak toplama grubu sorgularına açıkça izin vermelisiniz:
-
rules_version = '2';
kural kümenizin ilk satırıdır. Koleksiyon grubu sorguları, güvenlik kuralları sürüm 2'nin yeni yinelenen joker{name=**}
davranışını gerektirir. -
match /{path=**}/ [COLLECTION_ID] /{doc}
kullanarak koleksiyon grubunuz için bir kural yazın.
Örneğin, posts
alt koleksiyonlarını içeren forum
belgelerinde düzenlenmiş bir forum düşünün:
/forumlar/{forumid}/posts/{postid}
{
author: "some_auth_id",
authorname: "some_username",
content: "I just read a great story.",
}
Bu uygulamada, gönderileri 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ış herhangi bir kullanıcı, herhangi bir tek forumun gönderilerini alabilir:
db.collection("forums/technology/posts").get()
Ancak, mevcut kullanıcıya gönderilerini tüm forumlarda göstermek isterseniz ne olur? Tüm posts
koleksiyonlarından sonuçları 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;
}
}
}
Bununla birlikte, bu kuralların, hiyerarşiden bağımsız olarak kimlik posts
olan tüm koleksiyonlar için geçerli olacağını unutmayın. Örneğin, bu kurallar aşağıdaki posts
koleksiyonlarının tümü için geçerlidir:
-
/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ının da güvenlik kurallarınız tarafından belirlenen kısıtlamaları karşılaması gerekir. Örneğin, yukarıdaki stories
örneğinde yaptığımız gibi her forum gönderisine bir published
alan ekleyebiliriz:
/forumlar/{forumid}/posts/{postid}
{
author: "some_auth_id",
authorname: "some_username",
content: "I just read a great story.",
published: false
}
Daha sonra, published
durumuna ve gönderi author
göre posts
toplama 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:
Bir forumda yayınlanan yayınları herkes alabilir:
db.collection("forums/technology/posts").where('published', '==', true).get()
Bir yazarın yayınlanmış gönderilerini tüm forumlarda herkes alabilir:
db.collectionGroup("posts").where("author", "==", "some_auth_id").where('published', '==', true).get()
Yazarlar, yayınlanmış ve yayınlanmamış tüm gönderilerini tüm forumlardan alabilirler:
var user = firebase.auth().currentUser; db.collectionGroup("posts").where("author", "==", user.uid).get()
Koleksiyon grubuna ve belge yoluna göre belgeleri güvenli hale getirin ve sorgulayın
Bazı durumlarda, koleksiyon grubu sorgularını belge yoluna göre kısıtlamak isteyebilirsiniz. Bu kısıtlamaları oluşturmak için, belgeleri bir alana dayalı olarak güvenli hale getirmek ve sorgulamak için aynı teknikleri kullanabilirsiniz.
Çeşitli hisse senedi ve kripto para borsaları arasında her kullanıcının 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. Belgenin yolundan hangi kullanıcının bir transaction
belgesine sahip olduğunu bilsek de, iki şey yapmamıza izin verdiği için bu bilgiyi her transaction
belgesinde çoğaltırız:
Belge yolunda belirli bir
/users/{userid}
içeren belgelerle sınırlı toplama 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ğrulamayı dahil ediyoruz:
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
- Rol tabanlı erişim denetiminin daha ayrıntılı bir örneği için bkz. Kullanıcılar ve Gruplar için Veri Erişimini Güvenli Hale Getirme .
- Güvenlik kuralları referansını okuyun.