Ikuti semua informasi yang diumumkan di Firebase Summit, dan pelajari bagaimana Firebase dapat membantu Anda mempercepat pengembangan aplikasi dan menjalankan aplikasi dengan percaya diri. Pelajari Lebih Lanjut

Pelajari sintaks inti bahasa Aturan Keamanan Realtime Database

Tetap teratur dengan koleksi Simpan dan kategorikan konten berdasarkan preferensi Anda.

Aturan Keamanan Firebase Realtime Database memungkinkan Anda mengontrol akses ke data yang disimpan di database. Sintaks aturan yang fleksibel memungkinkan Anda membuat aturan yang cocok dengan apa pun, mulai dari semua penulisan ke database hingga operasi pada node individual.

Aturan Keamanan Realtime Database adalah konfigurasi deklaratif untuk database Anda. Ini berarti aturan ditentukan secara terpisah dari logika produk. Ini memiliki sejumlah keuntungan: klien tidak bertanggung jawab untuk menegakkan keamanan, implementasi buggy tidak akan membahayakan data Anda, dan mungkin yang paling penting, tidak perlu wasit perantara, seperti server, untuk melindungi data dari dunia luar.

Topik ini menjelaskan sintaks dasar dan struktur Aturan Keamanan Realtime Database yang digunakan untuk membuat kumpulan aturan lengkap.

Menyusun Aturan Keamanan Anda

Aturan Keamanan Realtime Database terdiri dari ekspresi mirip JavaScript yang terdapat dalam dokumen JSON. Struktur aturan Anda harus mengikuti struktur data yang telah Anda simpan di database Anda.

Aturan dasar mengidentifikasi satu set node yang akan diamankan, metode akses (misalnya, membaca, menulis) yang terlibat, dan kondisi di mana akses diperbolehkan atau ditolak. Dalam contoh berikut, kondisi kita akan berupa pernyataan true dan false yang sederhana, tetapi dalam topik berikutnya kita akan membahas cara yang lebih dinamis untuk menyatakan kondisi.

Jadi, misalnya, jika kita mencoba mengamankan child_node di bawah parent_node , sintaks umum yang harus diikuti adalah:

{
  "rules": {
    "parent_node": {
      "child_node": {
        ".read": <condition>,
        ".write": <condition>,
        ".validate": <condition>,
      }
    }
  }
}

Mari terapkan pola ini. Misalnya, Anda melacak daftar pesan dan memiliki data yang terlihat seperti ini:

{
  "messages": {
    "message0": {
      "content": "Hello",
      "timestamp": 1405704370369
    },
    "message1": {
      "content": "Goodbye",
      "timestamp": 1405704395231
    },
    ...
  }
}

Aturan Anda harus disusun dengan cara yang sama. Berikut seperangkat aturan untuk keamanan hanya-baca yang mungkin masuk akal untuk struktur data ini. Contoh ini mengilustrasikan bagaimana kita menspesifikasikan node database yang menerapkan aturan dan kondisi untuk mengevaluasi aturan pada node tersebut.

{
  "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"
      }
    }
  }
}

Operasi Aturan Dasar

Ada tiga jenis aturan untuk menegakkan keamanan berdasarkan jenis operasi yang dilakukan pada data: .write , .read , dan .validate . Berikut adalah ringkasan singkat dari tujuan mereka:

Jenis Aturan
.Baca Menjelaskan jika dan kapan data diizinkan untuk dibaca oleh pengguna.
.menulis Menjelaskan jika dan kapan data diperbolehkan untuk ditulis.
.mengesahkan Menentukan seperti apa nilai yang diformat dengan benar, apakah itu memiliki atribut turunan, dan tipe data.

Variabel Tangkap Wildcard

Semua pernyataan aturan menunjuk ke node. Pernyataan dapat menunjuk ke node tertentu atau menggunakan $ variabel tangkapan wildcard untuk menunjuk ke kumpulan node pada tingkat hierarki. Gunakan variabel tangkapan ini untuk menyimpan nilai kunci simpul untuk digunakan di dalam pernyataan aturan berikutnya. Teknik ini memungkinkan Anda menulis Ketentuan aturan yang lebih kompleks , sesuatu yang akan kita bahas lebih detail di topik berikutnya.

{
  "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')"
        }
      }
    }
  }
}

Variabel $ dinamis juga dapat digunakan secara paralel dengan nama jalur konstan. Dalam contoh ini, kami menggunakan variabel $other untuk mendeklarasikan aturan .validate yang memastikan bahwa widget tidak memiliki turunan selain title dan color . Penulisan apa pun yang akan menghasilkan pembuatan anak tambahan akan gagal.

{
  "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 }
    }
  }
}

Kaskade Aturan Baca dan Tulis

Aturan .write .read dari atas ke bawah, dengan aturan yang lebih dangkal mengesampingkan aturan yang lebih dalam. Jika aturan memberikan izin baca atau tulis pada jalur tertentu, maka aturan tersebut juga memberikan akses ke semua node anak di bawahnya. Pertimbangkan struktur berikut:

{
  "rules": {
     "foo": {
        // allows read to /foo/*
        ".read": "data.child('baz').val() === true",
        "bar": {
          /* ignored, since read was allowed already */
          ".read": false
        }
     }
  }
}

Struktur keamanan ini memungkinkan /bar/ untuk dibaca kapan pun /foo/ berisi baz anak dengan nilai true . Aturan ".read": false di bawah /foo/bar/ tidak berpengaruh di sini, karena akses tidak dapat dicabut oleh jalur anak.

Meskipun mungkin tidak langsung tampak intuitif, ini adalah bagian yang kuat dari bahasa aturan dan memungkinkan hak akses yang sangat kompleks untuk diimplementasikan dengan sedikit usaha. Ini akan diilustrasikan saat kita masuk ke keamanan berbasis pengguna nanti dalam panduan ini.

Perhatikan bahwa aturan .validate tidak menurun. Semua aturan validasi harus dipenuhi di semua tingkat hierarki agar penulisan diizinkan.

Aturan Bukan Filter

Aturan diterapkan secara atomik. Artinya, operasi baca atau tulis langsung gagal jika tidak ada aturan di lokasi tersebut atau di lokasi induk yang memberikan akses. Bahkan jika setiap jalur anak yang terpengaruh dapat diakses, membaca di lokasi induk akan gagal total. Pertimbangkan struktur ini:

{
  "rules": {
    "records": {
      "rec1": {
        ".read": true
      },
      "rec2": {
        ".read": false
      }
    }
  }
}

Tanpa memahami bahwa aturan dievaluasi secara atomis, sepertinya mengambil jalur /records/ akan mengembalikan rec1 tetapi tidak rec2 . Hasil sebenarnya, bagaimanapun, adalah kesalahan:

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
Catatan: Produk Firebase ini tidak tersedia di target Cuplikan Aplikasi.
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
}];
Cepat
Catatan: Produk Firebase ini tidak tersedia di target Cuplikan Aplikasi.
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
})
Jawa
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
  });
});
ISTIRAHAT
curl https://docs-examples.firebaseio.com/rest/records/
# response returns a PERMISSION_DENIED error

Karena operasi baca di /records/ bersifat atomik, dan tidak ada aturan baca yang memberikan akses ke semua data di bawah /records/ , ini akan menimbulkan kesalahan PERMISSION_DENIED . Jika kita mengevaluasi aturan ini di simulator keamanan di konsol Firebase kita, kita dapat melihat bahwa operasi baca ditolak karena tidak ada aturan baca yang mengizinkan akses ke jalur /records/ . Namun, perhatikan bahwa aturan untuk rec1 tidak pernah dievaluasi karena tidak sesuai dengan jalur yang kami minta. Untuk mengambil rec1 , kita perlu mengaksesnya secara langsung:

JavaScript
var db = firebase.database();
db.ref("records/rec1").once("value", function(snap) {
  // SUCCESS!
}, function(err) {
  // error callback is not called
});
Objective-C
Catatan: Produk Firebase ini tidak tersedia di target Cuplikan Aplikasi.
FIRDatabaseReference *ref = [[FIRDatabase database] reference];
[[ref child:@"records/rec1"] observeSingleEventOfType:FEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
    // SUCCESS!
}];
Cepat
Catatan: Produk Firebase ini tidak tersedia di target Cuplikan Aplikasi.
var ref = FIRDatabase.database().reference()
ref.child("records/rec1").observeSingleEventOfType(.Value, withBlock: { snapshot in
    // SUCCESS!
})
Jawa
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
  }
});
ISTIRAHAT
curl https://docs-examples.firebaseio.com/rest/records/rec1
# SUCCESS!

Pernyataan Tumpang Tindih

Ada kemungkinan lebih dari satu aturan untuk diterapkan ke sebuah node. Dalam kasus di mana beberapa ekspresi aturan mengidentifikasi sebuah node, metode akses ditolak jika salah satu kondisinya false :

{
  "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"
      }
    }
  }
}

Pada contoh di atas, pembacaan ke node message1 akan ditolak karena aturan kedua selalu false , meskipun aturan pertama selalu true .

Langkah selanjutnya

Anda dapat memperdalam pemahaman tentang Aturan Keamanan Firebase Realtime Database:

  • Pelajari konsep utama bahasa Aturan berikutnya, kondisi dinamis , yang memungkinkan Aturan Anda memeriksa otorisasi pengguna, membandingkan data yang ada dan yang masuk, memvalidasi data yang masuk, memeriksa struktur kueri yang berasal dari klien, dan banyak lagi.

  • Tinjau kasus penggunaan keamanan biasa dan definisi Aturan Keamanan Firebase yang mengatasinya .