Bu sayfa, istemcilerin bir belgedeki bazı alanlarda işlem yapmasına izin verirken diğerlerinde yapmamasına izin veren kurallar oluşturmak için Cloud Firestore Güvenlik Kurallarını nasıl kullanabileceğinizi açıklamak için Güvenlik Kurallarını Yapılandırma ve Güvenlik Kuralları için Koşullar Yazma bölümündeki kavramlara dayanmaktadır.
Bir belgede yapılan değişiklikleri belge düzeyinde değil alan düzeyinde kontrol etmek istediğiniz zamanlar olabilir.
Örneğin, bir müşterinin bir belge oluşturmasına veya değiştirmesine izin vermek, ancak bu belgedeki belirli alanları düzenlemesine izin vermemek isteyebilirsiniz. Veya bir istemcinin oluşturduğu herhangi bir belgenin her zaman belirli bir alan kümesi içermesini zorunlu kılmak isteyebilirsiniz. Bu kılavuz, Cloud Firestore Güvenlik Kurallarını kullanarak bu görevlerden bazılarını nasıl gerçekleştirebileceğinizi kapsar.
Yalnızca belirli alanlar için okuma erişimine izin verme
Cloud Firestore'daki okumalar belge düzeyinde gerçekleştirilir. Ya belgenin tamamını alırsınız ya da hiçbir şey alamazsınız. Kısmi bir belgeyi geri almanın bir yolu yoktur. Kullanıcıların bir belge içindeki belirli alanları okumasını engellemek için yalnızca güvenlik kurallarını kullanmak mümkün değildir.
Bir belgede bazı kullanıcılardan gizlemek istediğiniz belirli alanlar varsa, en iyi yol bunları ayrı bir belgeye koymak olacaktır. Örneğin, private
bir alt koleksiyonda şu şekilde bir belge oluşturmayı düşünebilirsiniz:
/çalışanlar/{emp_id}
name: "Alice Hamilton",
department: 461,
start_date: <timestamp>
/çalışanlar/{emp_id}/özel/finans
salary: 80000,
bonus_mult: 1.25,
perf_review: 4.2
Daha sonra iki koleksiyon için farklı erişim düzeylerine sahip güvenlik kuralları ekleyebilirsiniz. Bu örnekte, yalnızca özel kimlik doğrulama talebi role
Finance
eşit olan kullanıcıların bir çalışanın mali bilgilerini görüntüleyebileceğini söylemek için özel kimlik doğrulama taleplerini kullanıyoruz.
service cloud.firestore {
match /databases/{database}/documents {
// Allow any logged in user to view the public employee data
match /employees/{emp_id} {
allow read: if request.resource.auth != null
// Allow only users with the custom auth claim of "Finance" to view
// the employee's financial data
match /private/finances {
allow read: if request.resource.auth &&
request.resource.auth.token.role == 'Finance'
}
}
}
}
Belge oluşturmada alanları kısıtlama
Cloud Firestore şemasızdır, yani bir belgenin hangi alanları içerdiği konusunda veritabanı düzeyinde herhangi bir kısıtlama yoktur. Bu esneklik geliştirmeyi kolaylaştırsa da, istemcilerin yalnızca belirli alanları içeren veya başka alanlar içermeyen belgeler oluşturabildiğinden emin olmak istediğiniz zamanlar olacaktır.
Bu kuralları request.resource.data
nesnesinin keys
metodunu inceleyerek oluşturabilirsiniz. Bu, istemcinin bu yeni belgeye yazmaya çalıştığı tüm alanların listesidir. Bu alan kümesini hasOnly()
veya hasAny()
gibi işlevlerle birleştirerek, bir kullanıcının Cloud Firestore'a ekleyebileceği belge türlerini kısıtlayan bir mantık ekleyebilirsiniz.
Yeni belgelerde belirli alanların zorunlu kılınması
Bir restaurant
koleksiyonunda oluşturulan tüm belgelerin en azından bir name
, location
ve city
alanı içerdiğinden emin olmak istediğinizi varsayalım. Bunu yeni belgedeki anahtarlar listesinde hasAll()
öğesini çağırarak yapabilirsiniz.
service cloud.firestore {
match /databases/{database}/documents {
// Allow the user to create a document only if that document contains a name
// location, and city field
match /restaurant/{restId} {
allow create: if request.resource.data.keys().hasAll(['name', 'location', 'city']);
}
}
}
Bu, restoranların başka alanlarla da oluşturulmasına olanak tanır, ancak bir müşteri tarafından oluşturulan tüm belgelerin en az bu üç alanı içermesini sağlar.
Yeni belgelerde belirli alanların yasaklanması
Benzer şekilde, yasaklı alanlar listesine karşı hasAny()
işlevini kullanarak istemcilerin belirli alanlar içeren belgeler oluşturmasını engelleyebilirsiniz. Bu yöntem, bir belgenin bu alanlardan herhangi birini içermesi durumunda doğru olarak değerlendirilir; dolayısıyla, belirli alanları yasaklamak için muhtemelen sonucu reddetmek isteyebilirsiniz.
Örneğin, aşağıdaki örnekte, bu alanlar daha sonra bir sunucu çağrısı tarafından ekleneceği için istemcilerin, average_score
veya rating_count
alanı içeren bir belge oluşturmasına izin verilmez.
service cloud.firestore {
match /databases/{database}/documents {
// Allow the user to create a document only if that document does *not*
// contain an average_score or rating_count field.
match /restaurant/{restId} {
allow create: if (!request.resource.data.keys().hasAny(
['average_score', 'rating_count']));
}
}
}
Yeni belgeler için izin verilenler listesi oluşturma
Yeni belgelerde belirli alanları yasaklamak yerine yalnızca yeni belgelerde açıkça izin verilen alanların bir listesini oluşturmak isteyebilirsiniz. Daha sonra, oluşturulan yeni belgelerin yalnızca bu alanları (veya bu alanların bir alt kümesini) içerdiğinden, başkalarını içermediğinden emin olmak için hasOnly()
işlevini kullanabilirsiniz.
service cloud.firestore {
match /databases/{database}/documents {
// Allow the user to create a document only if that document doesn't contain
// any fields besides the ones listed below.
match /restaurant/{restId} {
allow create: if (request.resource.data.keys().hasOnly(
['name', 'location', 'city', 'address', 'hours', 'cuisine']));
}
}
}
Zorunlu ve isteğe bağlı alanların birleştirilmesi
Bazı alanları gerektirmek ve diğerlerine izin vermek için hasAll
ve hasOnly
işlemlerini güvenlik kurallarınızda bir araya getirebilirsiniz. Örneğin, bu örnek, tüm yeni belgelerin name
, location
ve city
alanlarını içermesini gerektirir ve isteğe bağlı olarak address
, hours
ve cuisine
alanlarına da izin verir.
service cloud.firestore {
match /databases/{database}/documents {
// Allow the user to create a document only if that document has a name,
// location, and city field, and optionally address, hours, or cuisine field
match /restaurant/{restId} {
allow create: if (request.resource.data.keys().hasAll(['name', 'location', 'city'])) &&
(request.resource.data.keys().hasOnly(
['name', 'location', 'city', 'address', 'hours', 'cuisine']));
}
}
}
Gerçek dünya senaryosunda, kodunuzun kopyalanmasını önlemek ve isteğe bağlı ve gerekli alanları tek bir listede daha kolay bir şekilde birleştirmek için bu mantığı bir yardımcı işleve taşımak isteyebilirsiniz:
service cloud.firestore {
match /databases/{database}/documents {
function verifyFields(required, optional) {
let allAllowedFields = required.concat(optional);
return request.resource.data.keys().hasAll(required) &&
request.resource.data.keys().hasOnly(allAllowedFields);
}
match /restaurant/{restId} {
allow create: if verifyFields(['name', 'location', 'city'],
['address', 'hours', 'cuisine']);
}
}
}
Güncelleme sırasında alanları kısıtlama
Yaygın bir güvenlik uygulaması, istemcilerin yalnızca bazı alanları düzenlemesine izin vermek, diğerlerini düzenlememesine izin vermektir. Bunu yalnızca önceki bölümde açıklanan request.resource.data.keys()
listesine bakarak gerçekleştiremezsiniz; çünkü bu liste, güncellemeden sonra bakılacağı gibi belgenin tamamını temsil eder ve bu nedenle istemcinin içermediği alanları içerir. değiştirmek.
Ancak diff()
işlevini kullanacaksanız, request.resource.data
dosyasını, güncellemeden önce veritabanındaki belgeyi temsil eden resource.data
nesnesiyle karşılaştırabilirsiniz. Bu, iki farklı harita arasındaki tüm değişiklikleri içeren bir nesne olan bir mapDiff
nesnesi oluşturur.
Bu MapDiff'te affectedKeys()
yöntemini çağırarak, bir düzenlemede değiştirilen bir dizi alanla karşılaşabilirsiniz. Daha sonra bu kümenin belirli öğeleri içerdiğinden (veya içermediğinden) emin olmak için hasOnly()
veya hasAny()
gibi işlevleri kullanabilirsiniz.
Bazı alanların değiştirilmesinin engellenmesi
affectedKeys()
tarafından oluşturulan kümede hasAny()
yöntemini kullanarak ve ardından sonucu reddederek, değiştirilmesini istemediğiniz alanları değiştirmeye çalışan tüm istemci isteklerini reddedebilirsiniz.
Örneğin, müşterilerin bir restoran hakkındaki bilgileri güncellemesine izin verip ortalama puanlarını veya yorum sayısını değiştirmemesini isteyebilirsiniz.
service cloud.firestore {
match /databases/{database}/documents {
match /restaurant/{restId} {
// Allow the client to update a document only if that document doesn't
// change the average_score or rating_count fields
allow update: if (!request.resource.data.diff(resource.data).affectedKeys()
.hasAny(['average_score', 'rating_count']));
}
}
}
Yalnızca belirli alanların değiştirilmesine izin verme
Değiştirilmesini istemediğiniz alanları belirtmek yerine, değiştirilmesini istediğiniz alanların listesini belirtmek için hasOnly()
işlevini de kullanabilirsiniz. Bu genellikle daha güvenli kabul edilir çünkü yeni belge alanlarına yazmaya, güvenlik kurallarınızda açıkça izin verene kadar varsayılan olarak izin verilmez.
Örneğin, average_score
ve rating_count
alanına izin vermemek yerine, istemcilerin yalnızca name
, location
, city
, address
, hours
ve cuisine
alanlarını değiştirmesine izin veren güvenlik kuralları oluşturabilirsiniz.
service cloud.firestore {
match /databases/{database}/documents {
match /restaurant/{restId} {
// Allow a client to update only these 6 fields in a document
allow update: if (request.resource.data.diff(resource.data).affectedKeys()
.hasOnly(['name', 'location', 'city', 'address', 'hours', 'cuisine']));
}
}
}
Bu, uygulamanızın gelecekteki bir yinelemesinde restoran belgelerinin bir telephone
alanı içermesi durumunda, siz geri dönüp bu alanı güvenlik kurallarınızdaki hasOnly()
listesine ekleyene kadar bu alanı düzenleme girişimlerinin başarısız olacağı anlamına gelir.
Alan türlerini zorunlu kılma
Cloud Firestore'un şemasız olmasının bir başka etkisi de, belirli alanlarda hangi tür verilerin depolanabileceğine ilişkin veritabanı düzeyinde herhangi bir yaptırımın bulunmamasıdır. Ancak bu, güvenlik kurallarında is
operatörüyle uygulayabileceğiniz bir şeydir.
Örneğin, aşağıdaki güvenlik kuralı, bir incelemenin score
alanının bir tam sayı olmasını, headline
, content
ve author_name
alanlarının dize olmasını ve review_date
bir zaman damgası olmasını zorunlu kılar.
service cloud.firestore {
match /databases/{database}/documents {
match /restaurant/{restId} {
// Restaurant rules go here...
match /review/{reviewId} {
allow create: if (request.resource.data.score is int &&
request.resource.data.headline is string &&
request.resource.data.content is string &&
request.resource.data.author_name is string &&
request.resource.data.review_date is timestamp
);
}
}
}
}
is
operatörü için geçerli veri türleri şunlardır bool
, bytes
, float
, int
, list
, latlng
, number
, path
, map
, string
ve timestamp
. is
operatörü aynı zamanda constraint
, duration
, set
ve map_diff
veri türlerini de destekler, ancak bunlar istemciler tarafından üretilmeyip güvenlik kuralları dilinin kendisi tarafından oluşturulduğundan, bunları çoğu pratik uygulamada nadiren kullanırsınız.
list
ve map
veri türlerinin jenerikler veya tür bağımsız değişkenleri için desteği yoktur. Başka bir deyişle, belirli bir alanın bir liste veya harita içermesini zorunlu kılmak için güvenlik kurallarını kullanabilirsiniz, ancak bir alanın tüm tamsayılardan veya tüm dizelerden oluşan bir liste içermesini zorunlu kılamazsınız.
Benzer şekilde, bir liste veya haritadaki belirli girişler için tür değerlerini zorlamak amacıyla güvenlik kurallarını kullanabilirsiniz (sırasıyla parantez gösterimini veya anahtar adlarını kullanarak), ancak bir haritadaki veya listedeki tüm üyelerin veri türlerini aynı anda zorunlu kılacak bir kısayol yoktur. bir kere.
Örneğin aşağıdaki kurallar, bir belgedeki tags
alanının bir liste içermesini ve ilk girdinin bir dize olmasını sağlar. Ayrıca product
alanının, dize olan bir ürün adını ve tamsayı olan bir miktarı içeren bir harita içermesini de sağlar.
service cloud.firestore {
match /databases/{database}/documents {
match /orders/{orderId} {
allow create: if request.resource.data.tags is list &&
request.resource.data.tags[0] is string &&
request.resource.data.product is map &&
request.resource.data.product.name is string &&
request.resource.data.product.quantity is int
}
}
}
}
Bir belgeyi hem oluştururken hem de güncellerken alan türlerinin zorunlu kılınması gerekir. Bu nedenle, güvenlik kurallarınızın hem oluşturma hem de güncelleme bölümlerinde çağırabileceğiniz bir yardımcı işlev oluşturmayı düşünebilirsiniz.
service cloud.firestore {
match /databases/{database}/documents {
function reviewFieldsAreValidTypes(docData) {
return docData.score is int &&
docData.headline is string &&
docData.content is string &&
docData.author_name is string &&
docData.review_date is timestamp;
}
match /restaurant/{restId} {
// Restaurant rules go here...
match /review/{reviewId} {
allow create: if reviewFieldsAreValidTypes(request.resource.data) &&
// Other rules may go here
allow update: if reviewFieldsAreValidTypes(request.resource.data) &&
// Other rules may go here
}
}
}
}
İsteğe bağlı alanlar için türleri uygulama
foo
bulunmadığı bir belgede request.resource.data.foo
çağrısının bir hatayla sonuçlanacağını ve dolayısıyla bu çağrıyı yapan herhangi bir güvenlik kuralının isteği reddedeceğini unutmamak önemlidir. Bu durumu request.resource.data
üzerinde get
metodunu kullanarak halledebilirsiniz. get
yöntemi, bir haritadan aldığınız alan mevcut değilse bu alan için varsayılan bir argüman sağlamanıza olanak tanır.
Örneğin, inceleme belgeleri aynı zamanda isteğe bağlı bir photo_url
alanı ve sırasıyla dizeler ve listeler olduğunu doğrulamak istediğiniz isteğe bağlı tags
alanını da içeriyorsa, bunu reviewFieldsAreValidTypes
işlevini aşağıdakine benzer bir şekilde yeniden yazarak gerçekleştirebilirsiniz:
function reviewFieldsAreValidTypes(docData) {
return docData.score is int &&
docData.headline is string &&
docData.content is string &&
docData.author_name is string &&
docData.review_date is timestamp &&
docData.get('photo_url', '') is string &&
docData.get('tags', []) is list;
}
Bu, tags
bulunduğu ancak liste olmayan belgeleri reddederken, tags
(veya photo_url
) alanı içermeyen belgelere de izin verir.
Kısmi yazmaya asla izin verilmez
Cloud Firestore Güvenlik Kuralları ile ilgili son bir not, istemcinin bir belgede değişiklik yapmasına izin vermesi veya düzenlemenin tamamını reddetmesidir. Aynı işlemde belgenizdeki bazı alanlara yazmayı kabul ederken diğerlerini reddeden güvenlik kuralları oluşturamazsınız.