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

Bahasa Aturan Keamanan

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

Aturan Keamanan Firebase memanfaatkan bahasa kustom yang fleksibel dan kuat yang mendukung berbagai kompleksitas dan perincian. Anda dapat membuat Aturan Anda sespesifik atau seumum mungkin untuk aplikasi Anda. Aturan Realtime Database menggunakan sintaks yang terlihat seperti JavaScript dalam struktur JSON. Aturan Cloud Firestore dan Cloud Storage menggunakan bahasa berdasarkan Common Expression Language (CEL) , yang dibangun di atas CEL dengan pernyataan match dan allow yang mendukung akses yang diberikan secara bersyarat.

Karena ini adalah bahasa khusus, bagaimanapun, ada kurva belajar. Gunakan panduan ini untuk lebih memahami bahasa Aturan saat Anda mempelajari lebih dalam aturan yang lebih kompleks.

Pilih produk untuk mempelajari lebih lanjut tentang aturannya.

Struktur dasar

Cloud Firestore

Aturan Keamanan Firebase di Cloud Firestore dan Cloud Storage menggunakan struktur dan sintaks berikut:

service <<name>> {
  // Match the resource path.
  match <<path>> {
    // Allow the request if the following conditions are true.
    allow <<methods>> : if <<condition>>
  }
}

Konsep kunci berikut ini penting untuk dipahami saat Anda membuat aturan:

  • Permintaan: Metode atau metode yang dipanggil dalam pernyataan allow . Ini adalah metode yang Anda izinkan untuk dijalankan. Metode standarnya adalah: get , list , create , update , dan delete . Metode kemudahan read dan write memungkinkan akses baca dan tulis yang luas pada database atau jalur penyimpanan yang ditentukan.
  • Jalur: Database atau lokasi penyimpanan, direpresentasikan sebagai jalur URI.
  • Aturan: Pernyataan allow , yang mencakup kondisi yang mengizinkan permintaan jika bernilai benar.

Masing-masing konsep ini dijelaskan secara lebih rinci di bawah ini.

Penyimpanan awan

Aturan Keamanan Firebase di Cloud Firestore dan Cloud Storage menggunakan struktur dan sintaks berikut:

service <<name>> {
  // Match the resource path.
  match <<path>> {
    // Allow the request if the following conditions are true.
    allow <<methods>> : if <<condition>>
  }
}

Konsep kunci berikut ini penting untuk dipahami saat Anda membuat aturan:

  • Permintaan: Metode atau metode yang dipanggil dalam pernyataan allow . Ini adalah metode yang Anda izinkan untuk dijalankan. Metode standarnya adalah: get , list , create , update , dan delete . Metode kemudahan read dan write memungkinkan akses baca dan tulis yang luas pada database atau jalur penyimpanan yang ditentukan.
  • Jalur: Database atau lokasi penyimpanan, direpresentasikan sebagai jalur URI.
  • Aturan: Pernyataan allow , yang mencakup kondisi yang mengizinkan permintaan jika bernilai benar.

Masing-masing konsep ini dijelaskan secara lebih rinci di bawah ini.

Basis Data Waktu Nyata

Di Realtime Database, Aturan Keamanan Firebase terdiri dari ekspresi seperti JavaScript yang terdapat dalam dokumen JSON.

Mereka menggunakan sintaks berikut:

{
  "rules": {
    "<<path>>": {
    // Allow the request if the condition for each method is true.
      ".read": <<condition>>,
      ".write": <<condition>>,
      ".validate": <<condition>>
    }
  }
}

Ada tiga elemen dasar dalam aturan:

  • Path: Lokasi database. Ini mencerminkan struktur JSON database Anda.
  • Permintaan: Ini adalah metode yang digunakan aturan untuk memberikan akses. Aturan read dan write memberikan akses baca dan tulis yang luas, sedangkan aturan validate bertindak sebagai verifikasi sekunder untuk memberikan akses berdasarkan data yang masuk atau yang ada.
  • Kondisi: Kondisi yang mengizinkan permintaan jika bernilai benar.

Konstruksi aturan

Cloud Firestore

Elemen dasar aturan di Cloud Firestore dan Cloud Storage adalah sebagai berikut:

  • Deklarasi service : Mendeklarasikan produk Firebase tempat aturan berlaku.
  • Blok match : Menentukan jalur dalam database atau keranjang penyimpanan tempat aturan berlaku.
  • Pernyataan allow : Menyediakan kondisi untuk memberikan akses, dibedakan berdasarkan metode. Metode yang didukung meliputi: get , list , create , update , delete , dan metode kemudahan read dan write .
  • Deklarasi function opsional: Memberikan kemampuan untuk menggabungkan dan menggabungkan kondisi untuk digunakan di beberapa aturan.

service berisi satu atau lebih blok match dengan pernyataan allow yang menyediakan kondisi yang memberikan akses ke permintaan. Variabel request dan resource tersedia untuk digunakan dalam ketentuan aturan. Bahasa Aturan Keamanan Firebase juga mendukung deklarasi function .

Versi sintaksis

Pernyataan syntax menunjukkan versi bahasa Aturan Firebase yang digunakan untuk menulis sumber. Versi bahasa terbaru adalah v2 .

rules_version = '2';
service cloud.firestore {
...
}

Jika tidak ada pernyataan rules_version yang diberikan, aturan Anda akan dievaluasi menggunakan mesin v1 .

Melayani

Deklarasi service menentukan produk atau layanan Firebase mana aturan Anda berlaku. Anda hanya dapat menyertakan satu deklarasi service per file sumber.

Cloud Firestore

service cloud.firestore {
 // Your 'match' blocks with their corresponding 'allow' statements and
 // optional 'function' declarations are contained here
}

Penyimpanan awan

service firebase.storage {
  // Your 'match' blocks with their corresponding 'allow' statements and
  // optional 'function' declarations are contained here
}

Jika Anda menentukan aturan untuk Cloud Firestore dan Cloud Storage menggunakan Firebase CLI, Anda harus menyimpannya dalam file terpisah.

Cocok

Blok match mendeklarasikan pola path yang cocok dengan jalur untuk operasi yang diminta ( request.path masuk). Isi match harus memiliki satu atau lebih blok match bersarang, pernyataan allow , atau deklarasi function . Jalur di blok match bersarang relatif terhadap jalur di blok match induk.

Pola path adalah nama seperti direktori yang mungkin menyertakan variabel atau karakter pengganti. Pola path memungkinkan untuk kecocokan segmen jalur tunggal dan segmen multi-jalur. Variabel apa pun yang terikat di path terlihat dalam cakupan match atau cakupan bersarang tempat path dideklarasikan.

Kecocokan terhadap pola path mungkin sebagian atau lengkap:

  • Kecocokan sebagian: Pola path adalah kecocokan awalan dari request.path .
  • Kecocokan lengkap: Pola path cocok dengan seluruh request.path .

Ketika kecocokan lengkap dibuat, aturan di dalam blok dievaluasi. Saat kecocokan sebagian dibuat, aturan match bertingkat diuji untuk melihat apakah path bersarang akan menyelesaikan kecocokan.

Aturan di setiap match lengkap dievaluasi untuk menentukan apakah akan mengizinkan permintaan. Jika ada aturan yang cocok yang memberikan akses, permintaan tersebut diizinkan. Jika tidak ada aturan yang cocok yang memberikan akses, permintaan akan ditolak.

// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
  // Partial match.
  match /example/{singleSegment} {   // `singleSegment` == 'hello'
    allow write;                     // Write rule not evaluated.
    // Complete match.
    match /nested/path {             // `singleSegment` visible in scope.
      allow read;                    // Read rule is evaluated.
    }
  }
  // Complete match.
  match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
    allow read;                      // Read rule is evaluated.
  }
}

Seperti yang ditunjukkan contoh di atas, deklarasi path mendukung variabel berikut:

  • Wildcard segmen tunggal: Variabel wildcard dideklarasikan di jalur dengan membungkus variabel dalam kurung kurawal: {variable} . Variabel ini dapat diakses dalam pernyataan match sebagai string .
  • Karakter pengganti rekursif: Karakter pengganti rekursif, atau multi-segmen, cocok dengan beberapa segmen jalur pada atau di bawah jalur. Karakter pengganti ini cocok dengan semua jalur di bawah lokasi yang Anda tetapkan. Anda dapat mendeklarasikannya dengan menambahkan string =** di akhir variabel segmen Anda: {variable=**} . Variabel ini dapat diakses dalam pernyataan match sebagai objek path .

Mengizinkan

Blok match berisi satu atau lebih pernyataan allow . Ini adalah aturan Anda yang sebenarnya. Anda dapat menerapkan aturan allow ke satu atau beberapa metode. Ketentuan pada pernyataan allow harus dievaluasi menjadi true agar Cloud Firestore atau Cloud Storage dapat mengabulkan setiap permintaan yang masuk. Anda juga dapat menulis pernyataan allow tanpa syarat, misalnya allow read . Namun, jika pernyataan allow tidak menyertakan suatu kondisi, ia selalu mengizinkan permintaan untuk metode tersebut.

Jika salah satu aturan allow untuk metode tersebut terpenuhi, permintaan tersebut diizinkan. Selain itu, jika aturan yang lebih luas memberikan akses, Aturan memberikan akses dan mengabaikan aturan yang lebih terperinci yang mungkin membatasi akses.

Pertimbangkan contoh berikut, di mana setiap pengguna dapat membaca atau menghapus file mereka sendiri. Aturan yang lebih terperinci hanya mengizinkan penulisan jika pengguna yang meminta penulisan memiliki file dan file tersebut adalah PNG. Seorang pengguna dapat menghapus file apa pun di subpath — bahkan jika itu bukan PNG — karena aturan sebelumnya mengizinkannya.

service firebase.storage {
  // Allow the requestor to read or delete any resource on a path under the
  // user directory.
  match /users/{userId}/{anyUserFile=**} {
    allow read, delete: if request.auth != null && request.auth.uid == userId;
  }

  // Allow the requestor to create or update their own images.
  // When 'request.method' == 'delete' this rule and the one matching
  // any path under the user directory would both match and the `delete`
  // would be permitted.

  match /users/{userId}/images/{imageId} {
    // Whether to permit the request depends on the logical OR of all
    // matched rules. This means that even if this rule did not explicitly
    // allow the 'delete' the earlier rule would have.
    allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
  }
}

metode

Setiap pernyataan allow mencakup metode yang memberikan akses untuk permintaan masuk dari metode yang sama.

metode Jenis permintaan
Metode kenyamanan
read Semua jenis permintaan baca
write Semua jenis permintaan tulis
Metode standar
get Baca permintaan untuk satu dokumen atau file
list Baca permintaan untuk pertanyaan dan koleksi
create Tulis dokumen atau file baru
update Tulis ke dokumen database yang ada atau perbarui metadata file
delete Hapus data

Anda tidak dapat tumpang tindih metode baca dalam blok match yang sama atau metode tulis yang bertentangan dalam deklarasi path yang sama.

Misalnya, aturan berikut akan gagal:

service bad.example {
  match /rules/with/overlapping/methods {
    // This rule allows reads to all authenticated users
    allow read: if request.auth != null;

    match another/subpath {
      // This secondary, more specific read rule causes an error
      allow get: if request.auth != null && request.auth.uid == "me";
      // Overlapping write methods in the same path cause an error as well
      allow write: if request.auth != null;
      allow create: if request.auth != null && request.auth.uid == "me";
    }
  }
}

Fungsi

Saat aturan keamanan Anda menjadi lebih kompleks, Anda mungkin ingin membungkus kumpulan kondisi dalam fungsi yang dapat Anda gunakan kembali di seluruh kumpulan aturan Anda. Aturan keamanan mendukung fungsi kustom. Sintaks untuk fungsi kustom sedikit mirip dengan JavaScript, tetapi fungsi aturan keamanan ditulis dalam bahasa khusus domain yang memiliki beberapa batasan penting:

  • Fungsi hanya dapat berisi satu pernyataan return . Mereka tidak dapat berisi logika tambahan. Misalnya, mereka tidak dapat menjalankan loop atau memanggil layanan eksternal.
  • Fungsi dapat secara otomatis mengakses fungsi dan variabel dari lingkup di mana mereka didefinisikan. Misalnya, fungsi yang ditentukan dalam cakupan service cloud.firestore memiliki akses ke variabel resource dan fungsi bawaan seperti get() dan exists() .
  • Fungsi dapat memanggil fungsi lain tetapi mungkin tidak berulang. Total kedalaman tumpukan panggilan dibatasi hingga 20.
  • Dalam aturan versi v2 , fungsi dapat mendefinisikan variabel menggunakan kata kunci let . Fungsi dapat memiliki hingga 10 binding let, tetapi harus diakhiri dengan pernyataan return.

Sebuah fungsi didefinisikan dengan kata kunci function dan mengambil nol atau lebih argumen. Misalnya, Anda mungkin ingin menggabungkan dua jenis kondisi yang digunakan dalam contoh di atas menjadi satu fungsi:

service cloud.firestore {
  match /databases/{database}/documents {
    // True if the user is signed in or the requested data is 'public'
    function signedInOrPublic() {
      return request.auth.uid != null || resource.data.visibility == 'public';
    }

    match /cities/{city} {
      allow read, write: if signedInOrPublic();
    }

    match /users/{user} {
      allow read, write: if signedInOrPublic();
    }
  }
}

Berikut adalah contoh yang menunjukkan argumen fungsi dan tugas let. Biarkan pernyataan penugasan harus dipisahkan oleh titik koma.

function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
  return isAuthor || isAdmin;
}

Perhatikan bagaimana penetapan isAdmin memberlakukan pencarian koleksi admin. Untuk evaluasi malas tanpa memerlukan pencarian yang tidak perlu, manfaatkan sifat hubungan pendek && (DAN) dan || (ATAU) perbandingan untuk memanggil fungsi kedua hanya jika isAuthor terbukti benar (untuk && perbandingan) atau salah (untuk || perbandingan).

function isAdmin(userId) {
  return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  // `||` is short-circuiting; isAdmin called only if isAuthor == false.
  return isAuthor || isAdmin(userId);
}

Menggunakan fungsi dalam aturan keamanan Anda membuatnya lebih mudah dipelihara seiring dengan bertambahnya kompleksitas aturan Anda.

Penyimpanan awan

Elemen dasar aturan di Cloud Firestore dan Cloud Storage adalah sebagai berikut:

  • Deklarasi service : Mendeklarasikan produk Firebase tempat aturan berlaku.
  • Blok match : Menentukan jalur dalam database atau keranjang penyimpanan tempat aturan berlaku.
  • Pernyataan allow : Menyediakan kondisi untuk memberikan akses, dibedakan berdasarkan metode. Metode yang didukung meliputi: get , list , create , update , delete , dan metode kemudahan read dan write .
  • Deklarasi function opsional: Memberikan kemampuan untuk menggabungkan dan menggabungkan kondisi untuk digunakan di beberapa aturan.

service berisi satu atau lebih blok match dengan pernyataan allow yang menyediakan kondisi yang memberikan akses ke permintaan. Variabel request dan resource tersedia untuk digunakan dalam ketentuan aturan. Bahasa Aturan Keamanan Firebase juga mendukung deklarasi function .

Versi sintaksis

Pernyataan syntax menunjukkan versi bahasa Aturan Firebase yang digunakan untuk menulis sumber. Versi bahasa terbaru adalah v2 .

rules_version = '2';
service cloud.firestore {
...
}

Jika tidak ada pernyataan rules_version yang diberikan, aturan Anda akan dievaluasi menggunakan mesin v1 .

Melayani

Deklarasi service menentukan produk atau layanan Firebase mana aturan Anda berlaku. Anda hanya dapat menyertakan satu deklarasi service per file sumber.

Cloud Firestore

service cloud.firestore {
 // Your 'match' blocks with their corresponding 'allow' statements and
 // optional 'function' declarations are contained here
}

Penyimpanan awan

service firebase.storage {
  // Your 'match' blocks with their corresponding 'allow' statements and
  // optional 'function' declarations are contained here
}

Jika Anda menentukan aturan untuk Cloud Firestore dan Cloud Storage menggunakan Firebase CLI, Anda harus menyimpannya dalam file terpisah.

Cocok

Blok match mendeklarasikan pola path yang cocok dengan jalur untuk operasi yang diminta ( request.path masuk). Isi match harus memiliki satu atau lebih blok match bersarang, pernyataan allow , atau deklarasi function . Jalur di blok match bersarang relatif terhadap jalur di blok match induk.

Pola path adalah nama seperti direktori yang mungkin menyertakan variabel atau karakter pengganti. Pola path memungkinkan untuk kecocokan segmen jalur tunggal dan segmen multi-jalur. Variabel apa pun yang terikat di path terlihat dalam cakupan match atau cakupan bersarang tempat path dideklarasikan.

Kecocokan terhadap pola path mungkin sebagian atau lengkap:

  • Kecocokan sebagian: Pola path adalah kecocokan awalan dari request.path .
  • Kecocokan lengkap: Pola path cocok dengan seluruh request.path .

Ketika kecocokan lengkap dibuat, aturan di dalam blok dievaluasi. Saat kecocokan sebagian dibuat, aturan match bertingkat diuji untuk melihat apakah path bersarang akan menyelesaikan kecocokan.

Aturan di setiap match lengkap dievaluasi untuk menentukan apakah akan mengizinkan permintaan. Jika ada aturan yang cocok yang memberikan akses, permintaan tersebut diizinkan. Jika tidak ada aturan yang cocok yang memberikan akses, permintaan akan ditolak.

// Given request.path == /example/hello/nested/path the following
// declarations indicate whether they are a partial or complete match and
// the value of any variables visible within the scope.
service firebase.storage {
  // Partial match.
  match /example/{singleSegment} {   // `singleSegment` == 'hello'
    allow write;                     // Write rule not evaluated.
    // Complete match.
    match /nested/path {             // `singleSegment` visible in scope.
      allow read;                    // Read rule is evaluated.
    }
  }
  // Complete match.
  match /example/{multiSegment=**} { // `multiSegment` == /hello/nested/path
    allow read;                      // Read rule is evaluated.
  }
}

Seperti yang ditunjukkan contoh di atas, deklarasi path mendukung variabel berikut:

  • Wildcard segmen tunggal: Variabel wildcard dideklarasikan di jalur dengan membungkus variabel dalam kurung kurawal: {variable} . Variabel ini dapat diakses dalam pernyataan match sebagai string .
  • Karakter pengganti rekursif: Karakter pengganti rekursif, atau multi-segmen, cocok dengan beberapa segmen jalur pada atau di bawah jalur. Karakter pengganti ini cocok dengan semua jalur di bawah lokasi yang Anda tetapkan. Anda dapat mendeklarasikannya dengan menambahkan string =** di akhir variabel segmen Anda: {variable=**} . Variabel ini dapat diakses dalam pernyataan match sebagai objek path .

Mengizinkan

Blok match berisi satu atau lebih pernyataan allow . Ini adalah aturan Anda yang sebenarnya. Anda dapat menerapkan aturan allow ke satu atau beberapa metode. Ketentuan pada pernyataan allow harus dievaluasi menjadi true agar Cloud Firestore atau Cloud Storage dapat mengabulkan setiap permintaan yang masuk. Anda juga dapat menulis pernyataan allow tanpa syarat, misalnya allow read . Namun, jika pernyataan allow tidak menyertakan suatu kondisi, ia selalu mengizinkan permintaan untuk metode tersebut.

Jika salah satu aturan allow untuk metode tersebut terpenuhi, permintaan tersebut diizinkan. Selain itu, jika aturan yang lebih luas memberikan akses, Aturan memberikan akses dan mengabaikan aturan yang lebih terperinci yang mungkin membatasi akses.

Pertimbangkan contoh berikut, di mana setiap pengguna dapat membaca atau menghapus file mereka sendiri. Aturan yang lebih terperinci hanya mengizinkan penulisan jika pengguna yang meminta penulisan memiliki file dan file tersebut adalah PNG. Seorang pengguna dapat menghapus file apa pun di subpath — bahkan jika itu bukan PNG — karena aturan sebelumnya mengizinkannya.

service firebase.storage {
  // Allow the requestor to read or delete any resource on a path under the
  // user directory.
  match /users/{userId}/{anyUserFile=**} {
    allow read, delete: if request.auth != null && request.auth.uid == userId;
  }

  // Allow the requestor to create or update their own images.
  // When 'request.method' == 'delete' this rule and the one matching
  // any path under the user directory would both match and the `delete`
  // would be permitted.

  match /users/{userId}/images/{imageId} {
    // Whether to permit the request depends on the logical OR of all
    // matched rules. This means that even if this rule did not explicitly
    // allow the 'delete' the earlier rule would have.
    allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
  }
}

metode

Setiap pernyataan allow mencakup metode yang memberikan akses untuk permintaan masuk dari metode yang sama.

metode Jenis permintaan
Metode kenyamanan
read Semua jenis permintaan baca
write Semua jenis permintaan tulis
Metode standar
get Baca permintaan untuk satu dokumen atau file
list Baca permintaan untuk pertanyaan dan koleksi
create Tulis dokumen atau file baru
update Tulis ke dokumen database yang ada atau perbarui metadata file
delete Hapus data

Anda tidak dapat tumpang tindih metode baca dalam blok match yang sama atau metode tulis yang bertentangan dalam deklarasi path yang sama.

Misalnya, aturan berikut akan gagal:

service bad.example {
  match /rules/with/overlapping/methods {
    // This rule allows reads to all authenticated users
    allow read: if request.auth != null;

    match another/subpath {
      // This secondary, more specific read rule causes an error
      allow get: if request.auth != null && request.auth.uid == "me";
      // Overlapping write methods in the same path cause an error as well
      allow write: if request.auth != null;
      allow create: if request.auth != null && request.auth.uid == "me";
    }
  }
}

Fungsi

Saat aturan keamanan Anda menjadi lebih kompleks, Anda mungkin ingin membungkus kumpulan kondisi dalam fungsi yang dapat Anda gunakan kembali di seluruh kumpulan aturan Anda. Aturan keamanan mendukung fungsi kustom. Sintaks untuk fungsi kustom sedikit mirip dengan JavaScript, tetapi fungsi aturan keamanan ditulis dalam bahasa khusus domain yang memiliki beberapa batasan penting:

  • Fungsi hanya dapat berisi satu pernyataan return . Mereka tidak dapat berisi logika tambahan. Misalnya, mereka tidak dapat menjalankan loop atau memanggil layanan eksternal.
  • Fungsi dapat secara otomatis mengakses fungsi dan variabel dari lingkup di mana mereka didefinisikan. Misalnya, fungsi yang ditentukan dalam cakupan service cloud.firestore memiliki akses ke variabel resource dan fungsi bawaan seperti get() dan exists() .
  • Fungsi dapat memanggil fungsi lain tetapi mungkin tidak berulang. Total kedalaman tumpukan panggilan dibatasi hingga 20.
  • Dalam aturan versi v2 , fungsi dapat mendefinisikan variabel menggunakan kata kunci let . Fungsi dapat memiliki hingga 10 binding let, tetapi harus diakhiri dengan pernyataan return.

Sebuah fungsi didefinisikan dengan kata kunci function dan mengambil nol atau lebih argumen. Misalnya, Anda mungkin ingin menggabungkan dua jenis kondisi yang digunakan dalam contoh di atas menjadi satu fungsi:

service cloud.firestore {
  match /databases/{database}/documents {
    // True if the user is signed in or the requested data is 'public'
    function signedInOrPublic() {
      return request.auth.uid != null || resource.data.visibility == 'public';
    }

    match /cities/{city} {
      allow read, write: if signedInOrPublic();
    }

    match /users/{user} {
      allow read, write: if signedInOrPublic();
    }
  }
}

Berikut adalah contoh yang menunjukkan argumen fungsi dan tugas let. Biarkan pernyataan penugasan harus dipisahkan oleh titik koma.

function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
  return isAuthor || isAdmin;
}

Perhatikan bagaimana penetapan isAdmin memberlakukan pencarian koleksi admin. Untuk evaluasi malas tanpa memerlukan pencarian yang tidak perlu, manfaatkan sifat hubungan pendek && (DAN) dan || (ATAU) perbandingan untuk memanggil fungsi kedua hanya jika isAuthor terbukti benar (untuk && perbandingan) atau salah (untuk || perbandingan).

function isAdmin(userId) {
  return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
  let isAuthor = article.author == userId;
  // `||` is short-circuiting; isAdmin called only if isAuthor == false.
  return isAuthor || isAdmin(userId);
}

Menggunakan fungsi dalam aturan keamanan Anda membuatnya lebih mudah dipelihara seiring dengan bertambahnya kompleksitas aturan Anda.

Basis Data Waktu Nyata

Seperti diuraikan di atas, Aturan Database Realtime mencakup tiga elemen dasar: lokasi database sebagai cermin dari struktur JSON database, jenis permintaan, dan kondisi pemberian akses.

Lokasi basis data

Struktur aturan Anda harus mengikuti struktur data yang telah Anda simpan di database Anda. Misalnya, dalam aplikasi obrolan dengan daftar pesan, Anda mungkin memiliki data yang terlihat seperti ini:

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

Aturan Anda harus mencerminkan struktur itu. Sebagai contoh:

  {
    "rules": {
      "messages": {
        "$message": {
          // only messages from the last ten minutes can be read
          ".read": "data.child('timestamp').val() > (now - 600000)",

          // new messages must have a string content and a number timestamp
          ".validate": "newData.hasChildren(['content', 'timestamp']) &&
                        newData.child('content').isString() &&
                        newData.child('timestamp').isNumber()"
        }
      }
    }
  }

Seperti yang ditunjukkan contoh di atas, Aturan Database Realtime mendukung variabel $location untuk mencocokkan segmen jalur. Gunakan awalan $ di depan segmen jalur Anda untuk mencocokkan aturan Anda dengan node turunan mana pun di sepanjang jalur.

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

Anda juga dapat menggunakan $variable secara paralel dengan nama jalur konstan.

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

metode

Dalam Realtime Database, ada tiga jenis aturan. Dua dari jenis aturan ini — read dan write — berlaku untuk metode permintaan masuk. Jenis aturan validate memberlakukan struktur data dan memvalidasi format dan konten data. Aturan menjalankan aturan .validate setelah memverifikasi bahwa aturan .write memberikan akses.

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

Secara default, jika tidak ada aturan yang mengizinkannya, akses di jalur ditolak.

Kondisi bangunan

Cloud Firestore

Kondisi adalah ekspresi boolean yang menentukan apakah operasi tertentu harus diizinkan atau ditolak. Variabel request dan resource menyediakan konteks untuk kondisi tersebut.

Variabel request

Variabel request mencakup bidang berikut dan informasi terkait:

request.auth

JSON Web Token (JWT) yang berisi kredensial autentikasi dari Firebase Authentication. token auth berisi kumpulan klaim standar dan klaim kustom apa pun yang Anda buat melalui Firebase Authentication. Pelajari lebih lanjut tentang Aturan dan Otentikasi Keamanan Firebase .

request.method

request.method dapat berupa salah satu metode standar atau metode kustom. Metode kemudahan read dan write juga ada untuk menyederhanakan aturan penulisan yang berlaku untuk semua metode standar hanya-baca atau semua-tulis.

request.params

request.params menyertakan data apa pun yang tidak secara khusus terkait dengan request.resource yang mungkin berguna untuk evaluasi. Dalam praktiknya, peta ini harus kosong untuk semua metode standar, dan harus berisi data non-sumber daya untuk metode khusus. Layanan harus berhati-hati untuk tidak mengganti nama atau memodifikasi jenis kunci dan nilai apa pun yang disajikan sebagai params.

request.path

request.path adalah jalur untuk resource target . Jalurnya relatif terhadap layanan. Segmen jalur yang berisi karakter aman non-url seperti / dikodekan dengan url.

Variabel resource

Sumber resource adalah nilai saat ini dalam layanan yang direpresentasikan sebagai peta pasangan nilai kunci. Referensi resource dalam suatu kondisi akan menghasilkan paling banyak satu pembacaan nilai dari layanan. Pencarian ini akan dihitung terhadap kuota terkait layanan apa pun untuk sumber daya. Untuk get permintaan, resource hanya akan dihitung terhadap kuota saat ditolak.

Operator dan prioritas operator

Gunakan tabel di bawah ini sebagai referensi untuk operator dan prioritasnya terkait dalam Aturan untuk Cloud Firestore dan Cloud Storage.

Diberikan ekspresi arbitrer a dan b , bidang f , dan indeks i .

Operator Keterangan Keterkaitan
a[i] a() af Indeks, panggilan, akses lapangan kiri ke kanan
!a -a Negasi unary kanan ke kiri
a/ba%ba*b Operator perkalian kiri ke kanan
a+b ab Operator tambahan kiri ke kanan
a>ba>=ba Operator relasional kiri ke kanan
a in b Keberadaan dalam daftar atau peta kiri ke kanan
a is type Perbandingan jenis, di mana type dapat berupa bool, int, float, nomor, string, daftar, peta, stempel waktu, durasi, jalur, atau latlng kiri ke kanan
a==ba!=b Operator perbandingan kiri ke kanan
a && b bersyarat DAN kiri ke kanan
a || b Bersyarat ATAU kiri ke kanan
a ? true_value : false_value Ekspresi terner kiri ke kanan

Penyimpanan awan

Kondisi adalah ekspresi boolean yang menentukan apakah operasi tertentu harus diizinkan atau ditolak. Variabel request dan resource menyediakan konteks untuk kondisi tersebut.

Variabel request

Variabel request mencakup bidang berikut dan informasi terkait:

request.auth

JSON Web Token (JWT) yang berisi kredensial autentikasi dari Firebase Authentication. token auth berisi kumpulan klaim standar dan klaim kustom apa pun yang Anda buat melalui Firebase Authentication. Pelajari lebih lanjut tentang Aturan dan Otentikasi Keamanan Firebase .

request.method

request.method dapat berupa salah satu metode standar atau metode kustom. Metode kemudahan read dan write juga ada untuk menyederhanakan aturan penulisan yang berlaku untuk semua metode standar hanya-baca atau semua-tulis.

request.params

request.params menyertakan data apa pun yang tidak secara khusus terkait dengan request.resource yang mungkin berguna untuk evaluasi. Dalam praktiknya, peta ini harus kosong untuk semua metode standar, dan harus berisi data non-sumber daya untuk metode khusus. Layanan harus berhati-hati untuk tidak mengganti nama atau memodifikasi jenis kunci dan nilai apa pun yang disajikan sebagai params.

request.path

request.path adalah jalur untuk resource target . Jalurnya relatif terhadap layanan. Segmen jalur yang berisi karakter aman non-url seperti / dikodekan dengan url.

Variabel resource

Sumber resource adalah nilai saat ini dalam layanan yang direpresentasikan sebagai peta pasangan nilai kunci. Referensi resource dalam suatu kondisi akan menghasilkan paling banyak satu pembacaan nilai dari layanan. Pencarian ini akan dihitung terhadap kuota terkait layanan apa pun untuk sumber daya. Untuk get permintaan, resource hanya akan dihitung terhadap kuota saat ditolak.

Operator dan prioritas operator

Gunakan tabel di bawah ini sebagai referensi untuk operator dan prioritasnya terkait dalam Aturan untuk Cloud Firestore dan Cloud Storage.

Diberikan ekspresi arbitrer a dan b , bidang f , dan indeks i .

Operator Keterangan Keterkaitan
a[i] a() af Indeks, panggilan, akses lapangan kiri ke kanan
!a -a Negasi unary kanan ke kiri
a/ba%ba*b Operator perkalian kiri ke kanan
a+b ab Operator tambahan kiri ke kanan
a>ba>=ba Operator relasional kiri ke kanan
a in b Keberadaan dalam daftar atau peta kiri ke kanan
a is type Perbandingan jenis, di mana type dapat berupa bool, int, float, nomor, string, daftar, peta, stempel waktu, durasi, jalur, atau latlng kiri ke kanan
a==ba!=b Operator perbandingan kiri ke kanan
a && b bersyarat DAN kiri ke kanan
a || b Bersyarat ATAU kiri ke kanan
a ? true_value : false_value Ekspresi terner kiri ke kanan

Basis Data Waktu Nyata

Kondisi adalah ekspresi boolean yang menentukan apakah operasi tertentu harus diizinkan atau ditolak. Anda dapat menentukan kondisi tersebut di Aturan Database Realtime dengan cara berikut.

Variabel yang telah ditentukan sebelumnya

Ada sejumlah variabel yang membantu dan telah ditentukan sebelumnya yang dapat diakses di dalam definisi aturan. Berikut adalah ringkasan singkat dari masing-masing:

Variabel yang telah ditentukan sebelumnya
sekarang Waktu saat ini dalam milidetik sejak zaman Linux. Ini bekerja sangat baik untuk memvalidasi stempel waktu yang dibuat dengan firebase.database.ServerValue.TIMESTAMP SDK.
akar RuleDataSnapshot yang mewakili jalur root di database Firebase seperti yang ada sebelum percobaan operasi.
data baru RuleDataSnapshot yang mewakili data sebagaimana adanya setelah percobaan operasi. Ini termasuk data baru yang sedang ditulis dan data yang sudah ada.
data RuleDataSnapshot yang mewakili data sebagaimana adanya sebelum percobaan operasi.
$ variabel Jalur karakter pengganti yang digunakan untuk mewakili id ​​dan kunci anak dinamis.
auth Mewakili muatan token pengguna yang diautentikasi.

Variabel ini dapat digunakan di mana saja dalam aturan Anda. Misalnya, aturan keamanan di bawah ini memastikan bahwa data yang ditulis ke /foo/ node harus berupa string yang kurang dari 100 karakter:

{
  "rules": {
    "foo": {
      // /foo is readable by the world
      ".read": true,

      // /foo is writable by the world
      ".write": true,

      // data written to /foo must be a string less than 100 characters
      ".validate": "newData.isString() && newData.val().length < 100"
    }
  }
}

Aturan berbasis data

Data apa pun dalam database Anda dapat digunakan dalam aturan Anda. Menggunakan variabel yang telah ditentukan sebelumnya root , data , dan newData , Anda dapat mengakses jalur apa pun seperti yang akan ada sebelum atau setelah peristiwa tulis.

Pertimbangkan contoh ini, yang memungkinkan operasi tulis selama nilai /allow_writes/ node adalah true , node induk tidak memiliki set flag readOnly , dan ada anak bernama foo dalam data yang baru ditulis:

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

Aturan berbasis kueri

Meskipun Anda tidak dapat menggunakan aturan sebagai filter, Anda dapat membatasi akses ke subkumpulan data dengan menggunakan parameter kueri dalam aturan Anda. Gunakan query. ekspresi dalam aturan Anda untuk memberikan akses baca atau tulis berdasarkan parameter kueri.

Misalnya, aturan berbasis kueri berikut menggunakan aturan keamanan berbasis pengguna dan aturan berbasis kueri untuk membatasi akses ke data dalam kumpulan baskets hanya ke keranjang belanja yang dimiliki pengguna aktif:

"baskets": {
  ".read": "auth.uid !== null &&
            query.orderByChild === 'owner' &&
            query.equalTo === auth.uid" // restrict basket access to owner of basket
}

Kueri berikut, yang menyertakan parameter kueri dalam aturan, akan berhasil:

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

Namun, kueri yang tidak menyertakan parameter dalam aturan akan gagal dengan kesalahan PermissionDenied :

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

Anda juga dapat menggunakan aturan berbasis kueri untuk membatasi jumlah data yang diunduh klien melalui operasi baca.

Misalnya, aturan berikut membatasi akses baca hanya ke 1000 hasil kueri pertama, seperti yang diurutkan berdasarkan prioritas:

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)

query. ekspresi tersedia di Aturan Database Realtime.

Ekspresi aturan berbasis kueri
Ekspresi Jenis Keterangan
query.orderByKey
query.orderByPriority
query.orderByValue
boolean Benar untuk kueri yang diurutkan berdasarkan kunci, prioritas, atau nilai. Salah sebaliknya.
query.orderByChild rangkaian
batal
Gunakan string untuk mewakili jalur relatif ke simpul anak. Misalnya, query.orderByChild === "address/zip" . Jika kueri tidak diurutkan oleh simpul anak, nilai ini adalah nol.
query.startAt
query.endAt
query.equalTo
rangkaian
nomor
boolean
batal
Mengambil batas kueri yang dieksekusi, atau mengembalikan null jika tidak ada kumpulan terikat.
query.limitToFirst
query.limitToLast
nomor
batal
Mengambil batas pada kueri yang dieksekusi, atau mengembalikan null jika tidak ada batas yang ditetapkan.

Operator

Aturan Realtime Database mendukung sejumlah operator yang dapat Anda gunakan untuk menggabungkan variabel dalam pernyataan kondisi. Lihat daftar lengkap operator dalam dokumentasi referensi .

Menciptakan kondisi

Kondisi Anda yang sebenarnya akan bervariasi berdasarkan akses yang ingin Anda berikan. Aturan sengaja menawarkan tingkat fleksibilitas yang sangat tinggi, sehingga aturan aplikasi Anda pada akhirnya bisa sesederhana atau serumit yang Anda inginkan.

Untuk beberapa panduan membuat Aturan sederhana yang siap produksi, lihat Aturan Keamanan Dasar .