Bu kılavuz, temel Firebase Güvenlik Kuralları dilini öğrenme rehberini temel alır. Firebase Realtime Database Güvenlik Kurallarınıza nasıl koşul ekleyeceğinizi gösterir.
Realtime Database Güvenlik Kurallarının birincil yapı taşı koşul'dur. CEVAP
koşul, belirli bir işlemin gerçekleşip gerçekleşmediğini belirleyen
izin verilen veya reddedilmelidir. Temel kurallar için true
ve false
değişmez değerlerini
ve koşulların gayet iyi gittiğini fark ettiniz. Realtime Database Güvenlik Kuralları dili,
aşağıdakileri gerçekleştirebilecek daha karmaşık koşullar yazmanın yollarını arar:
- Kullanıcı kimlik doğrulamasını kontrol edin
- Mevcut verileri yeni gönderilen verilerle karşılaştırarak
- Veritabanınızın farklı bölümlerine erişin ve bunları karşılaştırın
- Gelen verileri doğrulayın
- Güvenlik mantığı için gelen sorguların yapısını kullanın
Yol Segmentlerini Yakalamak için $ Değişkenlerini Kullanma
Tanıma yoluyla okuma veya yazma için yolun bölümlerini yakalayabilirsiniz.
$
önekine sahip değişkenleri yakalayın.
Bu, joker karakter olarak işlev görür ve ilgili anahtarın değerini içeride kullanmak üzere depolar
kural koşulları:
{ "rules": { "rooms": { // this rule applies to any child of /rooms/, the key for each room id // is stored inside $room_id variable for reference "$room_id": { "topic": { // the room's topic can be changed if the room id has "public" in it ".write": "$room_id.contains('public')" } } } } }
Dinamik $
değişkenleri sabit yolla paralel olarak da kullanılabilir
gösterir. Bu örnekte, şunu bildirmek için $other
değişkenini kullanıyoruz:
bir .validate
kuralı ile
widget
adlı kullanıcının title
ve color
dışında alt öğesi yok.
Başka alt öğelerin oluşturulmasına neden olacak yazma işlemleri başarısız olur.
{ "rules": { "widget": { // a widget can have a title or color attribute "title": { ".validate": true }, "color": { ".validate": true }, // but no other child paths are allowed // in this case, $other means any key excluding "title" and "color" "$other": { ".validate": false } } } }
Doğrulama
En yaygın güvenlik kuralı modellerinden biri, kullanıcının kimlik doğrulama durumuna Örneğin, uygulamanız oturum açmış kullanıcıların veri yazmasını sağlayabilirsiniz.
Uygulamanız Firebase Authentication kullanıyorsa request.auth
değişkeni
Veri isteyen istemcinin kimlik doğrulama bilgileri.
request.auth
hakkında daha fazla bilgi edinmek için referansa bakın
dokümanlarına göz atın.
Firebase Authentication, verileri kontrol etmenizi sağlamak için Firebase Realtime Database ile entegre olur
kullanıcı başına
erişimi olması gerekir. Bir kullanıcı kimlik doğrulaması yaptığında auth
değişkenin gerçek zamanlı veritabanı güvenlik kuralları kurallarınızdaki değişkeni kullanıcının
ekleyebilirsiniz. Bu bilgiler, benzersiz tanımlayıcılarını (uid
) içerir
Facebook kimliği veya e-posta adresi gibi bağlı hesap verileri ve
görürsünüz. Özel bir kimlik doğrulama sağlayıcı kullanıyorsanız kendi alanlarınızı ekleyebilirsiniz
ekler.
Bu bölümde, Firebase Realtime Database Güvenlik Kuralları dilinin kullanıcılarınızın kimlik doğrulama bilgilerini girin. Bu iki kavramı birleştirerek verilere erişimi kullanıcı kimliğine göre denetleyebilirsiniz.
auth
Değişkeni
Kurallardaki önceden tanımlanmış auth
değişkeni, şu değerden önce boş:
kimlik doğrulama gerçekleşir.
Kullanıcının kimliği Firebase Authentication ile doğrulandığında şu özellikleri içerir:
sağlayıcı | Kullanılan kimlik doğrulama yöntemi ("şifre", "anonim", "facebook", "github", "google", veya "Twitter"). |
uid | Tüm sağlayıcılar arasında benzersiz olduğu garanti edilen benzersiz kullanıcı kimliği. |
token |
Firebase Kimlik Doğrulama Kimliği jetonunun içeriği. Referansı göster
belgeleri
Ayrıntılı bilgi için auth.token .
|
Aşağıdaki örnek kural, auth
değişkenini kullanarak
her kullanıcı yalnızca kullanıcıya özel bir yola yazabilir:
{ "rules": { "users": { "$user_id": { // grants write access to the owner of this user account // whose uid must exactly match the key ($user_id) ".write": "$user_id === auth.uid" } } } }
Veritabanınızı Kimlik Doğrulama Koşullarını Destekleyecek Şekilde Yapılandırma
Veritabanınızı genellikle yazmanızı zorlayacak şekilde yapılandırmanız faydalı olur.
Rules daha kolay. Realtime Database içinde kullanıcı verilerini depolamak için yaygın olarak kullanılan bir kalıp
tüm kullanıcılarınızı tek bir users
düğümünde depolamak için
her kullanıcı için uid
değerleri. Örneğin,
Böylece, yalnızca giriş yapmış olan kullanıcı kendi verilerini görebilir; sizin kurallarınız,
olacaktır.
{ "rules": { "users": { "$uid": { ".read": "auth !== null && auth.uid === $uid" } } } }
Kimlik Doğrulaması ile İlgili Özel Hak Talepleriyle Çalışma
Farklı kullanıcılar için özel erişim denetimi gerektiren uygulamalarda Firebase Authentication
Geliştiricilerin Firebase kullanıcıları hakkında hak talepleri belirlemelerine olanak tanır.
Bu hak taleplerine kurallarınızdaki auth.token
değişkeninden erişebilirsiniz.
hasEmergencyTowel
öğesini kullanan kurallarla ilgili bir örneği aşağıda bulabilirsiniz.
özel hak talebi:
{ "rules": { "frood": { // A towel is about the most massively useful thing an interstellar // hitchhiker can have ".read": "auth.token.hasEmergencyTowel === true" } } }
kendileri için bir
özel kimlik doğrulama jetonları, isteğe bağlı olarak bu jetonlara hak talepleri ekleyebilir. Bu
kurallarınızdaki auth.token
değişkeninde hak talepleri mevcut.
Mevcut Veriler ile Yeni Verilerin Karşılaştırması
Önceden tanımlanmış data
değişkeni, önceki verilere bakmak için
bir yazma işlemi yapılır. Buna karşılık newData
değişkeni
değeri, yazma işlemi başarılı olursa var olacak yeni verileri içerir.
newData
, yazılan yeni verilerin birleştirilmiş sonucunu temsil eder
kullanabilirsiniz.
Örnek vermek gerekirse, bu kural yeni kayıtlar oluşturmamıza veya mevcut kayıtları silmemize ancak boş olmayan mevcut verilerde değişiklik yapmamak için şu adımları izleyin:
// we can write as long as old data or new data does not exist // in other words, if this is a delete or a create, but not an update ".write": "!data.exists() || !newData.exists()"
Diğer Yollardaki Verilere Referans Verme
Tüm veriler kurallar için ölçüt olarak kullanılabilir. Önceden tanımlanmış
root
, data
ve newData
değişkenlerini kullanarak
bir yazma etkinliğinden önce veya sonra var olduğu şekliyle herhangi bir yola erişebilir.
Şu örneği düşünün:
/allow_writes/
düğümü true
, üst düğümün öğesi yok
readOnly
işareti ayarlandı ve şurada foo
adında bir alt öğe var:
yeni yazılmış veriler:
".write": "root.child('allow_writes').val() === true && !data.parent().child('readOnly').exists() && newData.child('foo').exists()"
Veriler Doğrulanıyor
Veri yapılarını zorunlu kılmak ve verilerin biçimi ile içeriğini doğrulamak,
çalıştırıldıktan sonra çalıştırılan .validate
kurallarından
.write
kuralı erişim izni verdi. Aşağıda bir örnek verilmiştir
Yalnızca şu biçimdeki tarihlere izin veren .validate
kural tanımı
YYYY-AA-GG (1900-2099 arası) ve normal ifade kullanılarak kontrol edilir.
".validate": "newData.isString() && newData.val().matches(/^(19|20)[0-9][0-9][-\\/. ](0[1-9]|1[012])[-\\/. ](0[1-9]|[12][0-9]|3[01])$/)"
.validate
kuralları, basamaklamayan tek güvenlik kuralı türüdür. Varsa
doğrulama kuralı herhangi bir alt kayıtta başarısız olursa yazma işleminin tamamı reddedilir.
Ayrıca, veriler silindiğinde (yani yeni değer
null
olarak belirtilir).
Bunlar önemsiz noktalar gibi görünse de aslında yazı yazma konusunda önemli özelliklerdir. Güçlü Firebase Realtime Database Güvenlik Kuralları. Aşağıdaki kuralları göz önünde bulundurun:
{ "rules": { // write is allowed for all paths ".write": true, "widget": { // a valid widget must have attributes "color" and "size" // allows deleting widgets (since .validate is not applied to delete rules) ".validate": "newData.hasChildren(['color', 'size'])", "size": { // the value of "size" must be a number between 0 and 99 ".validate": "newData.isNumber() && newData.val() >= 0 && newData.val() <= 99" }, "color": { // the value of "color" must exist as a key in our mythical // /valid_colors/ index ".validate": "root.child('valid_colors/' + newData.val()).exists()" } } } }
Bu varyantı göz önünde bulundurarak aşağıdaki yazma işlemlerinin sonuçlarına bakın:
JavaScript
var ref = db.ref("/widget"); // PERMISSION_DENIED: does not have children color and size ref.set('foo'); // PERMISSION DENIED: does not have child color ref.set({size: 22}); // PERMISSION_DENIED: size is not a number ref.set({ size: 'foo', color: 'red' }); // SUCCESS (assuming 'blue' appears in our colors list) ref.set({ size: 21, color: 'blue'}); // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate ref.child('size').set(99);
Objective-C
FIRDatabaseReference *ref = [[[FIRDatabase database] reference] child: @"widget"]; // PERMISSION_DENIED: does not have children color and size [ref setValue: @"foo"]; // PERMISSION DENIED: does not have child color [ref setValue: @{ @"size": @"foo" }]; // PERMISSION_DENIED: size is not a number [ref setValue: @{ @"size": @"foo", @"color": @"red" }]; // SUCCESS (assuming 'blue' appears in our colors list) [ref setValue: @{ @"size": @21, @"color": @"blue" }]; // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate [[ref child:@"size"] setValue: @99];
Swift
var ref = FIRDatabase.database().reference().child("widget") // PERMISSION_DENIED: does not have children color and size ref.setValue("foo") // PERMISSION DENIED: does not have child color ref.setValue(["size": "foo"]) // PERMISSION_DENIED: size is not a number ref.setValue(["size": "foo", "color": "red"]) // SUCCESS (assuming 'blue' appears in our colors list) ref.setValue(["size": 21, "color": "blue"]) // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate ref.child("size").setValue(99);
Java
FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference ref = database.getReference("widget"); // PERMISSION_DENIED: does not have children color and size ref.setValue("foo"); // PERMISSION DENIED: does not have child color ref.child("size").setValue(22); // PERMISSION_DENIED: size is not a number Map<String,Object> map = new HashMap<String, Object>(); map.put("size","foo"); map.put("color","red"); ref.setValue(map); // SUCCESS (assuming 'blue' appears in our colors list) map = new HashMap<String, Object>(); map.put("size", 21); map.put("color","blue"); ref.setValue(map); // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate ref.child("size").setValue(99);
REST
# PERMISSION_DENIED: does not have children color and size curl -X PUT -d 'foo' \ https://docs-examples.firebaseio.com/rest/securing-data/example.json # PERMISSION DENIED: does not have child color curl -X PUT -d '{"size": 22}' \ https://docs-examples.firebaseio.com/rest/securing-data/example.json # PERMISSION_DENIED: size is not a number curl -X PUT -d '{"size": "foo", "color": "red"}' \ https://docs-examples.firebaseio.com/rest/securing-data/example.json # SUCCESS (assuming 'blue' appears in our colors list) curl -X PUT -d '{"size": 21, "color": "blue"}' \ https://docs-examples.firebaseio.com/rest/securing-data/example.json # If the record already exists and has a color, this will # succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) # will fail to validate curl -X PUT -d '99' \ https://docs-examples.firebaseio.com/rest/securing-data/example/size.json
Şimdi, .validate
yerine .write
kurallarını kullanarak aynı yapıya bakalım:
{ "rules": { // this variant will NOT allow deleting records (since .write would be disallowed) "widget": { // a widget must have 'color' and 'size' in order to be written to this path ".write": "newData.hasChildren(['color', 'size'])", "size": { // the value of "size" must be a number between 0 and 99, ONLY IF WE WRITE DIRECTLY TO SIZE ".write": "newData.isNumber() && newData.val() >= 0 && newData.val() <= 99" }, "color": { // the value of "color" must exist as a key in our mythical valid_colors/ index // BUT ONLY IF WE WRITE DIRECTLY TO COLOR ".write": "root.child('valid_colors/'+newData.val()).exists()" } } } }
Bu varyantta aşağıdaki işlemlerden herhangi biri başarılı olur:
JavaScript
var ref = new Firebase(URL + "/widget"); // ALLOWED? Even though size is invalid, widget has children color and size, // so write is allowed and the .write rule under color is ignored ref.set({size: 99999, color: 'red'}); // ALLOWED? Works even if widget does not exist, allowing us to create a widget // which is invalid and does not have a valid color. // (allowed by the write rule under "color") ref.child('size').set(99);
Objective-C
Firebase *ref = [[Firebase alloc] initWithUrl:URL]; // ALLOWED? Even though size is invalid, widget has children color and size, // so write is allowed and the .write rule under color is ignored [ref setValue: @{ @"size": @9999, @"color": @"red" }]; // ALLOWED? Works even if widget does not exist, allowing us to create a widget // which is invalid and does not have a valid color. // (allowed by the write rule under "color") [[ref childByAppendingPath:@"size"] setValue: @99];
Swift
var ref = Firebase(url:URL) // ALLOWED? Even though size is invalid, widget has children color and size, // so write is allowed and the .write rule under color is ignored ref.setValue(["size": 9999, "color": "red"]) // ALLOWED? Works even if widget does not exist, allowing us to create a widget // which is invalid and does not have a valid color. // (allowed by the write rule under "color") ref.childByAppendingPath("size").setValue(99)
Java
Firebase ref = new Firebase(URL + "/widget"); // ALLOWED? Even though size is invalid, widget has children color and size, // so write is allowed and the .write rule under color is ignored Map<String,Object> map = new HashMap<String, Object>(); map.put("size", 99999); map.put("color", "red"); ref.setValue(map); // ALLOWED? Works even if widget does not exist, allowing us to create a widget // which is invalid and does not have a valid color. // (allowed by the write rule under "color") ref.child("size").setValue(99);
REST
# ALLOWED? Even though size is invalid, widget has children color and size, # so write is allowed and the .write rule under color is ignored curl -X PUT -d '{size: 99999, color: "red"}' \ https://docs-examples.firebaseio.com/rest/securing-data/example.json # ALLOWED? Works even if widget does not exist, allowing us to create a widget # which is invalid and does not have a valid color. # (allowed by the write rule under "color") curl -X PUT -d '99' \ https://docs-examples.firebaseio.com/rest/securing-data/example/size.json
Bu görsel, .write
ile .validate
kuralları arasındaki farkları gösterir.
Gösterildiği gibi tüm bu kurallar .validate
kullanılarak yazılmalıdır.
newData.hasChildren()
kuralının olası istisnası,
silme işlemlerine izin verilmelidir.
Sorguya Dayalı Kurallar
Kuralları filtre olarak kullanamazsınız,
kurallarınızda sorgu parametrelerini kullanarak veri alt kümelerine erişimi sınırlayabilir.
Şu özelliklere göre okuma veya yazma erişimi vermek için kurallarınızda query.
ifadelerini kullanın:
sorgu parametreleridir.
Örneğin, aşağıdaki sorguya dayalı kural, kullanıcı tabanlı güvenlik kuralları kullanır
ve sorgu tabanlı kurallar aracılığıyla baskets
koleksiyonundaki verilere erişimi kısıtlayabilirsiniz.
yalnızca etkin kullanıcının sahip olduğu alışveriş sepetlerine ekleyin:
"baskets": {
".read": "auth.uid !== null &&
query.orderByChild === 'owner' &&
query.equalTo === auth.uid" // restrict basket access to owner of basket
}
Kuraldaki sorgu parametrelerini içeren aşağıdaki sorgu, başarılı:
db.ref("baskets").orderByChild("owner")
.equalTo(auth.currentUser.uid)
.on("value", cb) // Would succeed
Ancak kuraldaki parametreleri içermeyen sorgular,
PermissionDenied
hatası:
db.ref("baskets").on("value", cb) // Would fail with PermissionDenied
Müşterinin indireceği veri miktarını sınırlamak için sorgu tabanlı kurallar da kullanabilirsiniz. okuma işlemleriyle kontrol edilir.
Örneğin, aşağıdaki kural okuma erişimini yalnızca ilk 1.000 kullanıcı ile sınırlandırır. öncelik sırasına göre sıralanmış olarak:
messages: {
".read": "query.orderByKey &&
query.limitToFirst <= 1000"
}
// Example queries:
db.ref("messages").on("value", cb) // Would fail with PermissionDenied
db.ref("messages").limitToFirst(1000)
.on("value", cb) // Would succeed (default order by key)
Aşağıdaki query.
ifadeleri, Realtime Database Güvenlik Kurallarında kullanılabilir.
Sorguya dayalı kural ifadeleri | ||
---|---|---|
İfade | Tür | Açıklama |
sorgu.orderByKey sorgu.orderByPriority query.orderByValue |
boolean | Anahtar, öncelik veya değere göre sıralanmış sorgular için doğru değerini döndürür. Aksi takdirde False (yanlış) değerini alır. |
query.orderByChild | dize boş |
Bir alt düğümün göreli yolunu göstermek için dize kullanın. Örneğin,
query.orderByChild === "address/zip" Sorgu
alt düğüme göre sıralanmışsa bu değer boştur.
|
sorgu.başlangıç sorgu.endAt query.equalTo |
dize numara boole boş |
Yürütülen sorgunun sınırlarını alır veya varsa null değerini döndürür bağlı değil. |
query.limitToFirst query.limitToLast |
numara boş |
Yürütülen sorguda sınırı alır veya varsa null değerini döndürür sınır ayarlanmadı. |
Sonraki adımlar
Koşullarla ilgili olan bu konuşmadan sonra, Rules hakkında bilgi sahibisiniz ve şunları yapmaya hazırsınız:
Temel kullanım alanlarını ele almayı öğrenin ve uygulama geliştirme, Rules test ve dağıtımı:
- Kullanabileceğiniz önceden tanımlı Rules değişkenlerinin tamamı hakkında bilgi edinin en iyi uygulamaları görelim.
- Sık karşılaşılan senaryolar ile alakalı kurallar yazın.
- Güvenli olmayan kuralları tespit etmeniz ve bunlardan kaçınmanız gereken durumları inceleyerek bilginizi artırın.
- Firebase Local Emulator Suite ve bu paketi Rules test etmek için nasıl kullanabileceğiniz hakkında bilgi edinin.
- Rules dağıtımı için kullanılabilecek yöntemleri inceleyin.
Realtime Database ürününe özgü Rules özelliklerini öğrenin:
- Realtime Database sitenizi nasıl dizine ekleyeceğinizi öğrenin.
- Rules dağıtımı için REST API'yi inceleyin.