Halaman ini diterjemahkan oleh Cloud Translation API.
Switch to English

Pelajari sintaks inti bahasa Aturan Realtime Database

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

Aturan Keamanan Realtime Database adalah konfigurasi deklaratif untuk database Anda. Ini berarti bahwa 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 terpenting, tidak perlu wasit perantara, seperti server, untuk melindungi data dari dunia.

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 seperti JavaScript yang terdapat dalam dokumen JSON. Struktur aturan Anda harus mengikuti struktur data yang telah Anda simpan di database Anda.

Aturan dasar mengidentifikasi sekumpulan node yang akan diamankan, metode akses (misalnya, membaca, menulis) yang terlibat, dan kondisi di mana akses diizinkan atau ditolak. Dalam contoh berikut, kondisi kita akan menjadi pernyataan true dan false sederhana, tetapi di topik berikutnya kita akan membahas cara yang lebih dinamis untuk mengekspresikan kondisi.

Jadi, misalnya, jika kita mencoba mengamankan child_node 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 sekumpulan aturan untuk keamanan hanya baca yang mungkin masuk akal untuk struktur data ini. Contoh ini mengilustrasikan bagaimana kita menentukan node database tempat aturan berlaku dan kondisi untuk mengevaluasi aturan di 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 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 Mendefinisikan seperti apa nilai yang diformat dengan benar, apakah itu memiliki atribut turunan, dan tipe datanya.

Variabel Tangkapan Karakter Pengganti

Semua pernyataan aturan mengarah ke node. Pernyataan dapat mengarah ke node tertentu atau menggunakan variabel capture $ wildcard untuk mengarahkan ke kumpulan node pada tingkat hierarki. Gunakan variabel tangkap ini untuk menyimpan nilai kunci node 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 .validate selain title dan color . Tulisan apa pun yang akan menghasilkan anak tambahan yang dibuat 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 }
    }
  }
}

Aturan Baca dan Tulis Bertingkat

.read dan .write aturan bekerja dari atas ke bawah, dengan aturan dangkal override aturan yang lebih dalam. Jika aturan memberikan izin baca atau tulis pada jalur tertentu, aturan tersebut juga memberikan akses ke semua node turunan 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 setiap kali /foo/ berisi anak baz dengan nilai true . Aturan ".read": false bawah /foo/bar/ tidak berpengaruh di sini, karena akses tidak dapat dicabut oleh jalur turunan.

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

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

Aturan Bukanlah 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. Meskipun setiap jalur turunan yang terpengaruh dapat diakses, membaca di lokasi induk akan gagal sepenuhnya. Pertimbangkan struktur ini:

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

Tanpa memahami bahwa aturan dievaluasi secara atomik, tampaknya mengambil /records/ path akan mengembalikan rec1 tetapi tidak rec2 . Namun, hasil sebenarnya 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
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
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
  });
});
BERISTIRAHAT
curl https://docs-examples.firebaseio.com/rest/records/
# response returns a PERMISSION_DENIED error

Karena operasi baca di /records/ bersifat atomic, dan tidak ada aturan baca yang memberikan akses ke semua data di bawah /records/ , ini akan memunculkan kesalahan PERMISSION_DENIED . Jika kita mengevaluasi aturan ini di simulator keamanan di Firebase console , kita dapat melihat bahwa operasi baca ditolak karena tidak ada aturan baca yang mengizinkan akses ke /records/ path. Namun, perhatikan bahwa aturan untuk rec1 tidak pernah dievaluasi karena tidak ada di 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
FIRDatabaseReference *ref = [[FIRDatabase database] reference];
[[ref child:@"records/rec1"] observeSingleEventOfType:FEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
    // SUCCESS!
}];
Cepat
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
  }
});
BERISTIRAHAT
curl https://docs-examples.firebaseio.com/rest/records/rec1
# SUCCESS!

Pernyataan Tumpang tindih

Ada kemungkinan lebih dari satu aturan untuk diterapkan ke 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 Anda tentang Aturan Keamanan Firebase Realtime Database:

  • Pelajari konsep utama berikutnya dari bahasa Aturan, 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 umum dan definisi Aturan Keamanan Firebase yang mengatasinya .