Bu sayfada, Cloud Firestore Security Rules'in sorgularla nasıl etkileşime geçtiği açıklanmaktadır. Bu açıklama için Güvenlik kurallarını yapılandırma ve Güvenlik kuralları için yazma koşulları başlıklı makalelerdeki kavramlardan yararlanılmıştır. Bu makalede, güvenlik kurallarının yazabildiğiniz sorguları nasıl etkilediği daha ayrıntılı bir şekilde ele alınmakta ve sorgularınızın güvenlik kurallarınızla aynı kısıtlamaları kullandığından nasıl emin olabileceğiniz açıklanmaktadır. Bu sayfada, limit
ve orderBy
gibi sorgu özelliklerine dayalı sorgulara izin vermek veya sorguları reddetmek için güvenlik kurallarının nasıl yazılacağı da açıklanmaktadır.
Kurallar filtre değildir
Belgeleri almak için sorgu yazarken güvenlik kurallarının filtre olmadığını, sorguların "ya hep ya hiç" olduğunu unutmayın. Cloud Firestore, zamandan ve kaynaklardan tasarruf etmenizi 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, istemcinin okuma izninin olmadığı dokümanları potansiyel olarak 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
'ye göre 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 içeren bir veritabanı düşünün:
/stories/{storyid}
{
title: "A Great Story",
content: "Once upon a time...",
author: "some_auth_id",
published: false
}
Her doküman, title
ve content
alanlarına ek olarak erişim denetimi için kullanılacak author
ve published
alanlarını depolar. Bu örneklerde, uygulamanın author
alanını dokümanı oluşturan kullanıcının UID'sine ayarlamak için Firebase Authentication kullandığı varsayılmıştır. Firebase Authentication, güvenlik kurallarındaki request.auth
değişkenini de doldurur.
Aşağıdaki güvenlik kuralı, her bir story
öğesinin okuma ve yazma erişimini yazarıyla 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ığı story
dokümanların listesini gösteren bir sayfanın bulunduğunu varsayalım. Bu sayfayı doldurmak için aşağıdaki sorguyu kullanabilirsiniz. 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 kuralı kısıtlamalarıyla eşleşmez
// This query will fail
db.collection("stories").get()
Geçerli kullanıcı gerçekten her story
dokümanının 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 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 dokümanları potansiyel olarak içeriyorsa sorgu başarısız olur.
Buna karşılık aşağıdaki sorgu, author
alanında güvenlik kurallarıyla aynı kısıtlamayı içerdiğinden 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()
Bir alana göre dokümanları 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
koleksiyonunun okuma erişimini genişleterek tüm kullanıcıların, published
alanının true
olarak ayarlandığı story
dokümanlarını 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 yapılan 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ı, resource.data.published
değerinin herhangi bir sonuç için true
olduğunu garanti eder. Bu nedenle, bu sorgu güvenlik kurallarını karşılar ve verileri okumasına izin verilir.
OR
sorgu
Mantıksal bir OR
sorgusu (or
, in
veya array-contains-any
) bir kural grubuna göre değerlendirilirken Cloud Firestore, her karşılaştırma değerini ayrı olarak 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ı dokümanlar için x > 5
değerini 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 potansiyel dokümanlar için x > 5
işleminin
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, sorgunun limit
, offset
ve orderBy
özelliklerini içerir. Örneğin, güvenlik kurallarınız, getirilen 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 kümesi, sorgulara yerleştirilen kısıtlamaları değerlendiren güvenlik kurallarının nasıl yazılacağını gösterir. Bu örnekte, önceki stories
kural kümesi aşağıdaki değişikliklerle genişletilmiştir:
- Kural kümesi, okuma kuralını
get
velist
kurallarına ayırır. get
kuralı, tek dokümanların alınmasını herkese açık dokümanlarla veya kullanıcının yazdığı dokümanlarla kısıtlar.list
kuralı, sorgular içinget
ile aynı kısıtlamaları uygular. Sorgu sınırını da kontrol eder ve ardından sınırı olmayan veya 10'dan büyük sınıra sahip tüm sorguları reddeder.- Kural kümesi, kod yinelemesini ö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 bu koleksiyondan sonuç alır. Koleksiyon grubu sorguları sayesinde, aynı kimliğe sahip tüm koleksiyonları içeren 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 dokümanları güvenli hale getirme ve sorgulama
Güvenlik kurallarınızda, toplama grubu için bir kural yazarak toplama grubu sorgularına açıkça izin vermeniz gerekir:
rules_version = '2';
değerinin, kural grubunuzun ilk satırı olduğundan emin olun. Koleksiyon grubu sorguları, güvenlik kuralları 2 sürümünün yeniden kullanılabilir{name=**}
özelliğini gerektirir.match /{path=**}/[COLLECTION_ID]/{doc}
kullanarak koleksiyon grubunuz için bir kural yazın.
Örneğin, posts
alt koleksiyon içeren forum
belgeye ayrılmış bir forumu ele alalım:
/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ış tüm kullanıcılar, herhangi bir forumdaki yayınları alabilir:
db.collection("forums/technology/posts").get()
Ancak mevcut kullanıcıya tüm forumlardaki yayınlarını 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
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 posts
koleksiyonlarının tümü için geçerlidir:
/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 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 yayınına bir published
alanı ekleyebiliriz:
/forumlar/{forumid}/posts/{postid}
{
author: "some_auth_id",
authorname: "some_username",
content: "I just read a great story.",
published: false
}
Ardından, published
durumuna ve author
yayınına 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;
}
}
}
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, 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 doküman yoluna göre dokümanları güvenli hale getirme ve 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ı bir alana göre korumak ve sorgulamak için kullandığınız teknikleri kullanabilirsiniz.
Her kullanıcının çeşitli borsa ve kripto para borsalarındaki işlemlerini takip eden bir uygulamayı düşünün:
/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. Dokümanın yolundan transaction
dokümanına hangi kullanıcının sahip olduğunu bilsek de, bu bilgileri her transaction
dokümanında iki şekilde tekrarlıyoruz:
Belge yollarında belirli bir
/users/{userid}
içeren dokümanlarla 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
dokümanlarını alamaması için bu kısıtlamayıtransactions
koleksiyon grubundaki tüm sorgular için uygulayın.
Bu kısıtlamayı güvenlik kurallarımızda uygular ve user
alanı için veri doğrulamayı 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
- Rol tabanlı erişim denetimi hakkında daha ayrıntılı bir örnek için Kullanıcılar ve Gruplar için Veri Erişimini Güvence altına alma başlıklı makaleyi inceleyin.
- Güvenlik kuralları referansını okuyun.