Firebase Realtime Database güvenlik kuralları, veritabanınızda depolanan verilere erişimi kontrol etmenize olanak tanır. Esnek kural söz dizimi, veritabanınıza yapılan 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 bildirime dayalı yapılandırmadır. Bu, kuralların ürün mantığından ayrı olarak tanımlandığı anlamına gelir. Bu durumun çeşitli avantajları vardır: Müşteriler güvenliği zorunlu kılmaktan 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 Realtime Database Güvenlik Kuralları'nın temel söz dizimi ve yapısı açıklanmaktadır.
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 hale getirilecek bir dizi düğümü, ilgili erişim yöntemlerini (ör. okuma, yazma) ve erişimin izin verildiği veya reddedildiği koşulları tanımlar.
Aşağıdaki örneklerde koşullarımız basit true
ve false
ifadeleri olacaktır. Ancak bir sonraki konuda koşulları ifade etmenin daha dinamik yollarını ele alacağız.
Örneğin, parent_node
altında bir child_node
güvenliğini sağlamaya çalışıyorsak izlenecek genel söz dizimi şöyledir:
{ "rules": { "parent_node": { "child_node": { ".read": <condition>, ".write": <condition>, ".validate": <condition>, } } } }
Bu deseni uygulayalım. Örneğin, bir ileti 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 şekilde yapılandırılmalıdır. Bu veri yapısı için anlamlı olabilecek salt okunur güvenlik kurallarını aşağıda bulabilirsiniz. Bu örnekte, kuralların uygulandığı veritabanı düğümlerinin ve bu düğümlerdeki kuralların değerlendirilme koşullarının nasıl belirtildiği 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şlemin türüne göre güvenliği zorunlu kılmak için üç tür kural vardır: .write
, .read
ve .validate
. Bu kaynakların amaçlarının kısa bir özetini aşağıda bulabilirsiniz:
Kural Türleri | |
---|---|
.read | Verilerin kullanıcılar tarafından okunmasına izin verilip verilmediğini ve izin veriliyorsa ne zaman izin verildiğini açıklar. |
.write | Verilerin yazılmasına izin verilip verilmediğini ve izin veriliyorsa ne zaman izin verildiğini açıklar. |
.validate | Doğru biçimlendirilmiş bir değerin nasıl görüneceğini, alt özelliklere sahip olup olmadığını ve veri türünü tanımlar. |
Joker Karakterle Yakalama Değişkenleri
Tüm kural ifadeleri düğümleri gösterir. Bir ifade, belirli bir düğümü işaret edebilir veya hiyerarşi düzeyindeki düğüm kümelerini işaret etmek için $
joker karakter yakalama değişkenlerini kullanabilir. Düğüm anahtarlarının değerini sonraki kural ifadelerinde kullanmak üzere 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, $other
değişkenini kullanarak .validate
ve color
dışında alt öğesi olmayan widget
öğesini sağlayan bir .validate
kuralı tanımlıyoruz.title
Ek alt öğelerin oluşturulmasına neden olacak tüm 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 } } } }
Read and Write Rules Cascade
.read
ve .write
kuralları yukarıdan aşağıya doğru çalışır. Daha sığ kurallar, daha derin kuralları geçersiz kılar. Bir kural belirli bir yolda okuma veya yazma izni veriyorsa altındaki tüm alt düğümlere de erişim izni 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ı, /bar/
öğesinin, /foo/
öğesi true
değerine sahip bir baz
alt öğesi içerdiğinde okunmasına olanak tanır.
Erişim bir alt yol tarafından iptal edilemediğinden /foo/bar/
altındaki ".read": false
kuralı burada geçerli değildir.
Bu özellik 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ına olanak tanır. Bu durum, kılavuzun ilerleyen bölümlerinde kullanıcı tabanlı güvenlik konusunu ele aldığımızda açıklanacaktır.
.validate
kurallarının basamaklı olmadığını unutmayın. Yazma işlemine 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 olarak uygulanır. Bu, söz konusu konumda veya erişim izni veren bir üst konumda kural yoksa okuma veya yazma işleminin hemen başarısız olacağı anlamına gelir. Etkilenen tüm alt yollar erişilebilir olsa bile üst konumda okuma işlemi tamamen başarısız olur. Şu yapıyı göz önünde bulundurun:
{ "rules": { "records": { "rec1": { ".read": true }, "rec2": { ".read": false } } } }
Kuralların atomik olarak değerlendirildiğini anlamadan, /records/
yolunun getirilmesinin rec1
döndüreceği ancak rec2
döndürmeyeceğ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/
konumundaki 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ı verir. Bu kuralı Firebase konsolumuzdaki güvenlik simülatöründe değerlendirirsek okuma işlemine, /records/
yoluna erişime izin veren bir okuma kuralı olmadığı için izin verilmediğini görebiliriz. Ancak rec1
için kuralın, istediğimiz yolda olmadığı için hiçbir zaman değerlendirilmediğini unutmayın. rec1
öğesini getirmek 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 ifadeler
Bir düğüme birden fazla kural uygulanabilir. Birden fazla kural ifadesinin bir düğümü tanımladığı durumlarda, koşullardan herhangi biri 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 da ikinci kural her zaman false
olduğundan message1
düğümüne yapılan okuma işlemleri reddedilir.
Sonraki adımlar
Firebase Realtime Database güvenlik kuralları hakkındaki bilginizi derinleştirebilirsiniz:
Rules dilinin bir sonraki önemli kavramı olan dinamik koşullar hakkında bilgi edinin. Bu koşullar, Rules dilinin 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ır.
Tipik güvenlik kullanım alanlarını ve bunları ele alan Firebase Güvenlik Kuralları tanımlarını inceleyin.