Firebase Realtime Database Güvenlik Kuralları, veritabanınızda depolanan verilere erişimi kontrol etmenize olanak tanır. Esnek kurallar söz dizimi, veritabanınızdaki tüm yazma işlemlerinden tek tek düğümlerdeki işlemlere kadar her şeyle eşleşen kurallar oluşturmanıza olanak tanır.
Realtime Database Güvenlik Kuralları, veritabanınız için bildirim temelli yapılandırmadır. Bu, kuralların ürün mantığından ayrı olarak tanımlandığı anlamına gelir. Bunun birtakım avantajları vardır: Müşteriler güvenliğin uygulanmasından sorumlu değildir, hatalı uygulamalar verilerinizi tehlikeye atmaz ve belki de en önemlisi, verileri dış dünyadan korumak için sunucu gibi bir ara hakeme gerek yoktur.
Bu konu, tam kural kümeleri oluşturmak için kullanılan Realtime Database güvenlik kurallarının temel söz dizimini ve yapısını açıklar.
Güvenlik Kurallarınızı Yapılandırma
Realtime Database güvenlik kuralları, bir JSON belgesinde bulunan JavaScript benzeri ifadelerden oluşur. Kurallarınızın yapısı, veritabanınızda depoladığınız verilerin yapısına uygun olmalıdır.
Temel kurallar güvenliği sağlanacak bir düğüm grubunu, ilgili erişim yöntemlerini (ör. okuma, yazma) ve erişime izin verilen ya da reddedilecek koşulları tanımlar.
Aşağıdaki örneklerde koşullarımız basit true
ve false
ifadeleri olacak, ancak bir sonraki konuda koşulları ifade etmenin daha dinamik yollarını ele alacağız.
Örneğin, parent_node
altında bir child_node
öğesinin güvenliğini sağlamaya çalışırsak izlenecek genel söz dizimi şö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 aşağıdaki gibi 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. Aşağıda, bu veri yapısı için uygun olabilecek salt okunur güvenlik kuralları verilmiştir. Bu örnekte, kuralların geçerli olduğu veritabanı düğümlerini ve bu düğümlerde kuralların değerlendirilmesiyle ilgili koşulları nasıl belirttiğimiz gösterilmektedir.
{ "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şlem türüne bağlı olarak güvenliği zorunlu kılmak için üç tür kural vardır: .write
, .read
ve .validate
. Amaçlarının kısa bir özetini aşağıda bulabilirsiniz:
Kural Türleri | |
---|---|
okuyun | Verilerin kullanıcılar tarafından okunmasına izin verilip verilmediğini ve ne zaman izin verildiğini açıklar. |
.yazma | Verilerin yazılmasına izin verilip verilmediğini ve ne zaman izin verildiğini açıklar. |
.validate | Doğru biçimlendirilmiş bir değerin nasıl görüneceğini, alt özelliği olup olmadığını ve veri türünü tanımlar. |
Joker karakter yakalama değişkenleri
Tüm kural ifadeleri düğümleri işaret eder. Bir ifade, belirli bir düğümü işaretleyebilir veya hiyerarşinin bir seviyesindeki düğüm gruplarını işaretlemek için $
joker karakter 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, daha karmaşık Rules koşullar yazmanıza olanak tanır. Bu konuyu bir sonraki bölümde daha ayrıntılı olarak ele alacağız.
{ "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
öğesinin title
ve color
dışında alt öğelerinin bulunmamasını sağlayan bir .validate
kuralı tanımlamak için $other
değişkenini kullanıyoruz.
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 } } } }
Okuma ve Yazma Kuralları Kaskad
.read
ve .write
kuralları yukarıdan aşağıya doğru çalışır. Daha genel kurallar, daha özel kuralları geçersiz kılar. Bir kural belirli bir yolda okuma veya yazma izni veriyorsa bu yolun altındaki tüm alt düğümlere de erişim izni verir. Aşağıdaki yapıyı düşünün:
{ "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 alt baz
içerdiğinde /bar/
öğesinin okunmasına olanak tanır.
Erişim, alt yol tarafından iptal edilemediğinden /foo/bar/
altındaki ".read": false
kuralı burada geçerli değildir.
Bu, ilk bakışta sezgisel görünmese de kurallar dilinin güçlü bir parçasıdır ve çok karmaşık erişim ayrıcalıklarının minimum çabayla uygulanmasını sağlar. Bu konu, bu kılavuzun ilerleyen bölümlerinde kullanıcıya dayalı güvenlikle ilgili olarak ele alınacaktır.
.validate
kurallarının basamaklandırılmadığını unutmayın. Yazma işlemine izin verilmesi için tüm doğrulama kurallarının hiyerarşinin tüm seviyelerinde karşılanması gerekir.
Kurallar filtre değildir
Kurallar atomik olarak uygulanır. Bu, söz konusu konumda veya üst konumda erişim izni veren bir kural yoksa okuma veya yazma işleminin hemen başarısız olacağı anlamına gelir. Etkilenen her alt yola erişilebilse bile üst konumda okuma işlemi tamamen başarısız olur. Şu yapıyı düşünün:
{ "rules": { "records": { "rec1": { ".read": true }, "rec2": { ".read": false } } } }
Kuralların atomik olarak değerlendirildiğini anlamadan, /records/
yolunun getirilmesi sonucunda rec1
değerinin döndürüleceği, rec2
değerinin ise döndürülmeyeceği düşünülebilir. Ancak gerçek 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 });
Objective-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 }];
Swift
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 }); });
REST
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 izni veren bir okuma kuralı olmadığından bu işlem PERMISSION_DENIED
hatası oluşturur. Bu kuralı Firebase konsolumuzdaki güvenlik simülatöründe değerlendirirsek hiçbir okuma kuralı /records/
yoluna erişime izin vermediği için okuma işleminin reddedildiğini görebiliriz. Ancak rec1
kuralının, istenen yolda olmadığı için hiçbir zaman değerlendirilmediğini unutmayın. rec1
değerini almak için 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 });
Objective-C
FIRDatabaseReference *ref = [[FIRDatabase database] reference]; [[ref child:@"records/rec1"] observeSingleEventOfType:FEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) { // SUCCESS! }];
Swift
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 } });
REST
curl https://docs-examples.firebaseio.com/rest/records/rec1 # SUCCESS!
Çakışan İfadeler
Bir düğüme birden fazla kural uygulanabilir. Birden fazla kural ifadesinin bir düğümü tanımladığı durumlarda, koşullardan herhangisi false
ise 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 true
olsa bile ikinci kural her zaman false
olduğu için message1
düğümüne yapılan okuma işlemleri reddedilir.
Sonraki adımlar
Firebase Gerçek Zamanlı Veritabanı Güvenlik Kuralları hakkında daha fazla bilgi edinebilirsiniz:
Rules dilinin bir sonraki önemli kavramı olan dinamik koşulları öğrenin. Bu, Rules'ün kullanıcı yetkilendirmesini kontrol etmesine, mevcut verileri 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ır.
Tipik güvenlik kullanım alanlarını ve bunları ele alan Firebase Güvenlik Kuralı tanımlarını inceleyin.