Gerçek Zamanlı Veritabanı Kurallarında kullanım koşulları

Bu kılavuz üzerine inşa çekirdek Firebase Güvenlik Kuralları dil öğrenmek sizin Firebase Gerçek Zamanlı Veritabanı Güvenliği Kuralları için koşullar nasıl ekleneceğini gösteren rehber.

Gerçek Zamanlı Veri Tabanı Güvenlik Kuralları birincil yapı taşı durumdur. Bir koşul, belirli bir işleme izin verilip verilmeyeceğini belirleyen bir Boole ifadesidir. Temel kuralları için kullanan true ve false koşulları gibi değişmezleri prefectly iyi çalışıyor. Ancak Gerçek Zamanlı Veritabanı Güvenlik Kuralları dili, size aşağıdakileri yapabilen daha karmaşık koşullar yazmanın yollarını sunar:

  • Kullanıcı kimlik doğrulamasını kontrol edin
  • Mevcut verileri yeni gönderilen verilere göre değerlendirin
  • 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

Sen ile yakalama değişkenleri bildirerek bir okuma veya yazma için yolun bölümlerini yakalayabilir $ önek. Bu bir joker karakter işlevi görür ve bu anahtarın değerini kural koşullarında kullanmak üzere saklar:

{
  "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şkenler de sabit yol adları ile paralel olarak kullanılabilir. Bu örnekte, kullandığınız $other bir ilan değişken .validate kural olmasını sağlar bu widget dışında hiçbir çocuk babasıdır title ve color . 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 }
    }
  }
}

kimlik doğrulama

En yaygın güvenlik kuralı kalıplarından biri, kullanıcının kimlik doğrulama durumuna göre erişimi kontrol etmektir. Örneğin, uygulamanız yalnızca oturum açmış kullanıcıların veri yazmasına izin vermek isteyebilir.

Uygulama Firebase Kimlik kullanıyorsa, request.auth değişken verilerini talep eden müşteri için kimlik doğrulama bilgilerini içerir. Hakkında daha fazla bilgi için request.auth , bkz başvuru belgeleri .

Firebase Authentication, koşulları kullanarak kullanıcı bazında veri erişimini kontrol etmenize izin vermek için Firebase Realtime Database ile entegre olur. Bir kullanıcının kimliğini doğrular sonra, auth sizin Gerçek Zamanlı Veri Tabanı Güvenlik Kuralları kurallarda değişken kullanıcının bilgileriyle doldurulur. Bu bilgiler kendi benzersiz tanımlayıcı (içerir uid ) yanı sıra bir Facebook kimliği veya e-posta adresi ve diğer bilgiyi olarak bağlantılı hesap verilerini,. Özel bir yetkilendirme sağlayıcısı uygularsanız, kullanıcınızın yetkilendirme yüküne kendi alanlarınızı ekleyebilirsiniz.

Bu bölüm, Firebase Gerçek Zamanlı Veritabanı Güvenlik Kuralları dilinin kullanıcılarınız hakkında kimlik doğrulama bilgileriyle nasıl birleştirileceğini açıklar. Bu iki kavramı birleştirerek, kullanıcı kimliğine dayalı verilere erişimi kontrol edebilirsiniz.

auth Değişken

Önceden tanımlanmış auth kimlik doğrulama işlemi yapılmadan önce kurallarda değişken sıfırdır.

Bir kullanıcı ile doğrulandıktan sonra Firebase Kimlik aşağıdaki özelliklerini içerecektir:

Sağlayıcı Kullanılan kimlik doğrulama yöntemi ("şifre", "anonim", "facebook", "github", "google" veya "twitter").
kullanıcı kimliği Tüm sağlayıcılar arasında benzersiz olması garanti edilen benzersiz bir kullanıcı kimliği.
jeton Firebase Auth ID belirtecinin içeriği. Referans belgelerine bakın auth.token fazla ayrıntı için.

İşte kullanan bir örnek kuraldır auth her kullanıcının yalnızca bir kullanıcıya özgü yoluna yazabilirsiniz sağlamak için değişken:

{
  "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ı Kural yazmayı kolaylaştıracak şekilde yapılandırmak genellikle yararlıdır. Gerçek zamanlı Veritabanında kullanıcı verilerini depolamak için yaygın bir desen tek daki tüm kullanıcıların saklamaktır users çocukları olan düğüm uid her kullanıcı için değerler. Bu verilere erişimi, yalnızca oturum açmış kullanıcının kendi verilerini görebileceği şekilde kısıtlamak isteseydiniz, kurallarınız şöyle görünürdü.

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "auth != null && auth.uid == $uid"
      }
    }
  }
}

Kimlik Doğrulama Özel Talepleriyle Çalışma

Farklı kullanıcılar için özel erişim kontrolü gerektiren uygulamalar için Firebase Kimlik geliştiriciler izin veren bir Firebase kullanıcı grubu iddiaları . Bu iddialar içinde erişilebilir olan auth.token Kurallarınızda değişken. İşte faydalanmak kurallara örneğidir hasEmergencyTowel özel istem:

{
  "rules": {
    "frood": {
      // A towel is about the most massively useful thing an interstellar
      // hitchhiker can have
      ".read": "auth.token.hasEmergencyTowel === true"
    }
  }
}

Oluşturan geliştiriciler kendi özel kimlik doğrulama jetonları isteğe bu jetonlar için iddiaları ekleyebilir. Bu iddialar üzerine avaialble auth.token Kurallarınızda değişken.

Mevcut Veriler ve Yeni Veriler

Önceden tanımlanmış data değişken gerçekleşen bir yazma işlemi önce verilere başvurmak için kullanılır. Tersine, newData değişken yazma işlemi başarılı olursa var olacaktır yeni veriler içeriyor. newData yeni veriler yazılır ve mevcut veriler olma birleştirilmiş sonucu temsil eder.

Örnek vermek gerekirse, bu kural yeni kayıtlar oluşturmamıza veya mevcut olanları silmemize izin verir, ancak mevcut boş olmayan verilerde değişiklik yapmamıza izin vermez:

// 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

Herhangi bir veri, kurallar için kriter olarak kullanılabilir. Önceden tanımlanmış değişkenler kullanarak root , data ve newData , bunun önce veya yazma olaydan sonra mevcut gibi herhangi yoluna erişebilir.

Sürece yazma işlemleri sağlayan bu örneği var sayalım değeri olarak /allow_writes/ düğümdür true bir yok üst düğüm readOnly bayrağı seti ve adında bir çocuk var foo yeni yazılmış verilerdeki:

".write": "root.child('allow_writes').val() === true &&
          !data.parent().child('readOnly').exists() &&
          newData.child('foo').exists()"

Verileri Doğrulama

Veri yapılarını İcrası ve biçimini kullanarak yapılmalıdır verinin içeriğini doğrulayarak .validate bir sonra çalıştırılır kuralları, .write kural erişim vermek başarır. Aşağıda bir örneği verilmiştir .validate sadece normal bir ifade kullanarak kontrol edilir yıllar 1900-2099 arası formatında YYYY-AA-GG, tarihleri verir kural tanımı.

".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 kaskad yok güvenlik kuralının tek türdür. Herhangi bir alt kayıtta herhangi bir doğrulama kuralı başarısız olursa, yazma işleminin tamamı reddedilecektir. Verileri silinir Ayrıca, validate tanımları (olduğunu, yeni değer yazılır edilirken olduğu göz ardı edilir null ).

Bunlar önemsiz noktalar gibi görünebilir, ancak aslında güçlü Firebase Gerçek Zamanlı Veritabanı Güvenlik Kuralları yazmak için önemli özelliklerdir. 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 değişkeni 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);
Amaç-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];
hızlı
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);
DİNLENME
# 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 aynı yapısına Bakalım, ancak kullanarak .write yerine kurallarını .validate :

{
  "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);
Amaç-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];
hızlı
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);
DİNLENME
# 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 arasındaki farklılıkları göstermektedir .write ve .validate kurallara. Gösterdiği gibi, bu kuralların tüm kullanılarak yazılmalıdır .validate olası istisna ile, newData.hasChildren() silme izin gerekip gerekmediğini bağlı olacağını kural.

Sorgu Tabanlı Kurallar

Eğer rağmen filtre olarak kurallarını kullanamaz , Kurallarınızda sorgu parametreleri kullanılarak veri alt kümeleri erişimi sınırlayabilir. Kullanım query. Sorgu parametrelerine göre okuma veya yazma erişimi vermek için kurallarınızdaki ifadeler.

Örneğin, aşağıdaki sorgu tabanlı kural kullanan kullanıcı tabanlı güvenlik kurallarını verilere erişimi kısıtlamak için ve sorgu tabanlı kurallar baskets aktif kullanıcının sahip tek alışveriş sepetleri için koleksiyon:

"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ı olur:

db.ref("baskets").orderByChild("owner")
                 .equalTo(auth.currentUser.uid)
                 .on("value", cb)                 // Would succeed

Ancak, kural parametrelerini içermiyor sorguları ile başarısız olur PermissionDenied hata:

db.ref("baskets").on("value", cb)                 // Would fail with PermissionDenied

Bir istemcinin okuma işlemleri aracılığıyla ne kadar veri indirdiğini sınırlamak için sorgu tabanlı kuralları da kullanabilirsiniz.

Örneğin, aşağıdaki kural, önceliğe göre sıralandığı şekilde, bir sorgunun yalnızca ilk 1000 sonucuna okuma erişimini sınırlar:

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. ifadeler Gerçek Zamanlı Veritabanı Güvenlik Kurallarında mevcuttur.

Sorgu tabanlı kural ifadeleri
ifade Tür Açıklama
sorgu.orderByKey
sorgu.orderByPriority
sorgu.orderByValue
boole Anahtar, öncelik veya değere göre sıralanan sorgular için geçerlidir. Aksi takdirde yanlış.
sorgu.orderByChild dize
boş
Bir alt düğümün göreli yolunu temsil etmek için bir dize kullanın. Örneğin, query.orderByChild == "address/zip" . Sorgu bir alt düğüm tarafından sıralanmıyorsa, bu değer boştur.
sorgu.startAt
sorgu.endAt
sorgu.equalTo
dize
numara
boole
boş
Yürütülen sorgunun sınırlarını alır veya sınır kümesi yoksa null değerini döndürür.
sorgu.limitToFirst
sorgu.limitToLast
numara
boş
Yürütülen sorgudaki sınırı alır veya ayarlanmış bir sınır yoksa null değerini döndürür.

Sonraki adımlar

Koşullarla ilgili bu tartışmadan sonra, daha gelişmiş bir Kural anlayışına sahip olursunuz ve şunları yapmaya hazırsınız:

Temel kullanım senaryolarının nasıl ele alınacağını öğrenin ve Kuralları geliştirmek, test etmek ve dağıtmak için iş akışını öğrenin:

Gerçek Zamanlı Veritabanına özgü Kuralları öğrenin özellikleri: