Firebase Gerçek Zamanlı Veritabanı Güvenlik Kuralları, veritabanınızda depolanan verilere erişimi kontrol etmenize olanak tanır. Esnek kural sözdizimi, veritabanınıza yapılan tüm yazmalardan tek tek düğümlerdeki işlemlere kadar her şeyle eşleşen kurallar oluşturmanıza olanak tanır.
Gerçek Zamanlı Veritabanı Güvenlik Kuralları, veritabanınız için bildirime dayalı yapılandırmadır. Bu, kuralların ürün mantığından ayrı tanımlandığı anlamına gelir. Bunun bir dizi avantajı vardır: istemciler güvenliği uygulamaktan sorumlu değildir, hatalı uygulamalar verilerinizi tehlikeye atmaz ve belki de en önemlisi, verileri dünyadan korumak için sunucu gibi bir ara hakeme gerek yoktur.
Bu konuda, eksiksiz kural kümeleri oluşturmak için kullanılan Gerçek Zamanlı Veritabanı Güvenlik Kurallarının temel sözdizimi ve yapısı açıklanmaktadır.
Güvenlik Kurallarınızı Yapılandırma
Gerçek Zamanlı Veritabanı Güvenlik Kuralları, bir JSON belgesinde yer alan JavaScript benzeri ifadelerden oluşur. Kurallarınızın yapısı, veritabanınızda sakladığınız verilerin yapısını takip etmelidir.
Temel kurallar, güvenliği sağlanacak bir dizi düğümü , ilgili erişim yöntemlerini (örn. okuma, yazma) ve erişimin hangi koşullar altında izin verildiğini veya reddedildiğini tanımlar. Aşağıdaki örneklerde, koşullarımız basit true
ve false
ifadeler olacak, ancak bir sonraki konuda koşulları ifade etmenin daha dinamik yollarını ele alacağız.
Örneğin, bir child_node
bir parent_node
altında korumaya çalışıyorsak izlenecek genel sözdizimi şöyledir:
{ "rules": { "parent_node": { "child_node": { ".read": <condition>, ".write": <condition>, ".validate": <condition>, } } } }
Bu kalıbı uygulayalım. Örneğin, bir mesaj listesini takip ettiğinizi ve şuna benzer verilere sahip olduğunuzu varsayalım:
{ "messages": { "message0": { "content": "Hello", "timestamp": 1405704370369 }, "message1": { "content": "Goodbye", "timestamp": 1405704395231 }, ... } }
Kurallarınız benzer bir şekilde yapılandırılmalıdır. Burada, bu veri yapısı için anlamlı olabilecek salt okunur güvenlik için bir dizi kural verilmiştir. Bu örnek, kuralların uygulanacağı veritabanı düğümlerini nasıl belirlediğimizi ve bu düğümlerdeki kuralları değerlendirme koşullarını gösterir.
{ "rules": { // For requests to access the 'messages' node... "messages": { // ...and the individual wildcarded 'message' nodes beneath // (we'll cover wildcarding variables more a bit later).... "$message": { // For each message, allow a read operation if <condition>. In this // case, we specify our condition as "true", so read access is always granted. ".read": "true", // For read-only behavior, we specify that for write operations, our // condition is false. ".write": "false" } } } }
Temel Kural İşlemleri
Veriler üzerinde gerçekleştirilen işlemin türüne bağlı olarak güvenliği zorlamak için üç tür kural vardır: .write
, .read
ve .validate
. İşte amaçlarının kısa bir özeti:
Kural Türleri | |
---|---|
.Okumak | Verilerin kullanıcılar tarafından okunmasına izin verilip verilmediğini ve ne zaman izin verildiğini açıklar. |
.yazmak | Verilerin yazılmasına izin verilip verilmediğini ve ne zaman izin verildiğini açıklar. |
.doğrula | Doğru biçimlendirilmiş bir değerin nasıl görüneceğini, alt niteliklere sahip olup olmadığını ve veri türünü tanımlar. |
Joker Karakter Yakalama Değişkenleri
Tüm kural ifadeleri düğümlere işaret eder. Bir ifade, belirli bir düğüme işaret edebilir veya hiyerarşi düzeyindeki düğüm kümelerine işaret etmek için $
joker yakalama değişkenlerini kullanabilir. Sonraki kural ifadelerinde kullanmak üzere düğüm anahtarlarının değerini depolamak için bu yakalama değişkenlerini kullanın. Bu teknik, bir sonraki konuda daha ayrıntılı olarak ele alacağımız daha karmaşık Kural koşulları yazmanıza olanak tanır.
{ "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 yol adlarıyla paralel olarak da kullanılabilir. Bu örnekte, widget
title
ve color
dışında alt öğesi olmamasını sağlayan bir .validate
kuralı bildirmek için $other
değişkenini kullanıyoruz. Ek alt öğelerin oluşturulmasına neden olacak herhangi bir yazma işlemi 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 } } } }
Okuma ve Yazma Kuralları Kademeli
.read
ve .write
kuralları, daha derin kuralları geçersiz kılan daha sığ kurallarla yukarıdan aşağıya çalışır. Bir kural, belirli bir yolda okuma veya yazma izinleri veriyorsa, altındaki tüm alt düğümlere erişim de verir. Aşağıdaki yapıyı göz önünde bulundurun:
{ "rules": { "foo": { // allows read to /foo/* ".read": "data.child('baz').val() === true", "bar": { /* ignored, since read was allowed already */ ".read": false } } } }
Bu güvenlik yapısı, / /foo/
true
değerine sahip bir çocuk baz
içerdiği her durumda / /bar/
öğesinin okunmasına izin verir. /foo/bar/
altındaki ".read": false
kuralının burada bir etkisi yoktur, çünkü erişim bir alt yol tarafından iptal edilemez.
Hemen sezgisel görünmese de bu, kural dilinin güçlü bir parçasıdır ve çok karmaşık erişim ayrıcalıklarının minimum çabayla uygulanmasına izin verir. Bu, bu kılavuzun ilerleyen kısımlarında kullanıcı tabanlı güvenliğe girdiğimizde açıklanacaktır.
.validate
kurallarının kademeli olmadığını unutmayın. Yazmaya izin verilmesi için tüm doğrulama kurallarının hiyerarşinin tüm düzeylerinde karşılanması gerekir.
Kurallar Filtre Değildir
Kurallar atomik bir şekilde uygulanır. Bu, söz konusu konumda veya üst konumda erişim sağlayan bir kural yoksa okuma veya yazma işleminin hemen başarısız olduğu anlamına gelir. Etkilenen her alt yola erişilebilir olsa bile, üst konumda okuma tamamen başarısız olacaktır. Bu yapıyı göz önünde bulundurun:
{ "rules": { "records": { "rec1": { ".read": true }, "rec2": { ".read": false } } } }
Kuralların atomik olarak değerlendirildiğini anlamadan, /records/
yolunu getirmek rec1
döndürürken rec2
döndürmez gibi görünebilir. Ancak asıl sonuç bir hatadır:
JavaScript
var db = firebase.database(); db.ref("records").once("value", function(snap) { // success method is not called }, function(err) { // error callback triggered with PERMISSION_DENIED });
Amaç-C
FIRDatabaseReference *ref = [[FIRDatabase database] reference]; [[_ref child:@"records"] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) { // success block is not called } withCancelBlock:^(NSError * _Nonnull error) { // cancel block triggered with PERMISSION_DENIED }];
Süratli
var ref = FIRDatabase.database().reference() ref.child("records").observeSingleEventOfType(.Value, withBlock: { snapshot in // success block is not called }, withCancelBlock: { error in // cancel block triggered with PERMISSION_DENIED })
java
FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference ref = database.getReference("records"); ref.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot snapshot) { // success method is not called } @Override public void onCancelled(FirebaseError firebaseError) { // error callback triggered with PERMISSION_DENIED }); });
DİNLENMEK
curl https://docs-examples.firebaseio.com/rest/records/ # response returns a PERMISSION_DENIED error
/records/
adresindeki okuma işlemi atomik olduğundan ve /records/
altındaki tüm verilere erişim sağlayan bir okuma kuralı olmadığından, bu bir PERMISSION_DENIED
hatası verir. Bu kuralı Firebase konsolumuzdaki güvenlik simülatöründe değerlendirirsek, hiçbir okuma kuralının /records/
yoluna erişime izin vermediği için okuma işleminin reddedildiğini görebiliriz. Ancak, rec1
kuralının, istediğimiz yolda olmadığı için hiçbir zaman değerlendirilmediğini unutmayın. rec1
getirmek için ona doğrudan erişmemiz gerekir:
JavaScript
var db = firebase.database(); db.ref("records/rec1").once("value", function(snap) { // SUCCESS! }, function(err) { // error callback is not called });
Amaç-C
FIRDatabaseReference *ref = [[FIRDatabase database] reference]; [[ref child:@"records/rec1"] observeSingleEventOfType:FEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) { // SUCCESS! }];
Süratli
var ref = FIRDatabase.database().reference() ref.child("records/rec1").observeSingleEventOfType(.Value, withBlock: { snapshot in // SUCCESS! })
java
FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference ref = database.getReference("records/rec1"); ref.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot snapshot) { // SUCCESS! } @Override public void onCancelled(FirebaseError firebaseError) { // error callback is not called } });
DİNLENMEK
curl https://docs-examples.firebaseio.com/rest/records/rec1 # SUCCESS!
Çakışan İfadeler
Birden fazla kuralın bir düğüme uygulanması mümkündür. Birden çok kural ifadesinin bir düğümü tanımlaması durumunda, koşullardan herhangi biri false
erişim yöntemi reddedilir:
{ "rules": { "messages": { // A rule expression that applies to all nodes in the 'messages' node "$message": { ".read": "true", ".write": "true" }, // A second rule expression applying specifically to the 'message1` node "message1": { ".read": "false", ".write": "false" } } } }
Yukarıdaki örnekte, ilk kural her zaman false
olsa da ikinci kural her zaman true
olduğundan, message1
düğümüne yapılan okumalar reddedilecektir.
Sonraki adımlar
Firebase Gerçek Zamanlı Veritabanı Güvenlik Kuralları konusundaki anlayışınızı derinleştirebilirsiniz:
Kurallarınızın kullanıcı yetkilendirmesini kontrol etmesine, mevcut ve gelen verileri karşılaştırmasına, gelen verileri doğrulamasına, istemciden gelen sorguların yapısını kontrol etmesine ve daha fazlasına olanak tanıyan, Kurallar dilinin bir sonraki ana konsepti olan dinamik koşulları öğrenin.
Tipik güvenlik kullanım durumlarını ve bunları ele alan Firebase Güvenlik Kuralları tanımlarını inceleyin.