Aturan Keamanan Firebase menggunakan bahasa yang fleksibel, andal, dan kustom yang mendukung berbagai tingkat kerumitan dan perincian. Anda dapat membuat Aturan yang
sespesifik atau seumum mungkin untuk aplikasi Anda. Aturan Realtime Database menggunakan
sintaksis yang serupa dengan JavaScript dalam struktur JSON.
Aturan Cloud Firestore dan Cloud Storage menggunakan bahasa berdasarkan
Common Expression Language (CEL), yang
dikembangkan dari CEL dengan pernyataan match
dan allow
yang mendukung akses yang diberikan
secara bersyarat.
Namun, mengingat ini adalah bahasa kustom, tentu diperlukan proses pembelajaran. Gunakan panduan ini untuk lebih memahami bahasa Aturan sembari mempelajari lebih dalam aturan yang lebih kompleks.
Pilih produk untuk mempelajari lebih lanjut aturannya.
Struktur dasar
Cloud Firestore
Aturan Keamanan Firebase di Cloud Firestore dan Cloud Storage menggunakan struktur dan sintaksis berikut:
service <<name>> {
// Match the resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow <<methods>> : if <<condition>>
}
}
Berikut konsep utama yang perlu dipahami saat mem-build aturan:
- Permintaan: Satu atau beberapa metode yang dipanggil dalam pernyataan
allow
. Ini adalah metode yang Anda izinkan untuk berjalan. Metode standarnya adalah:get
,list
,create
,update
, dandelete
. Metoderead
danwrite
yang praktis akan mengaktifkan akses baca dan tulis yang luas pada jalur database atau penyimpanan yang ditentukan. - Jalur: Lokasi database atau penyimpanan, direpresentasikan sebagai jalur URI.
- Aturan: Pernyataan
allow
, berisi kondisi yang mengizinkan permintaan jika kondisi tersebut bernilai benar.
Baca penjelasan selengkapnya mengenai setiap konsep tersebut di bawah.
Cloud Storage
Aturan Keamanan Firebase di Cloud Firestore dan Cloud Storage menggunakan struktur dan sintaksis berikut:
service <<name>> {
// Match the resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow <<methods>> : if <<condition>>
}
}
Berikut konsep utama yang perlu dipahami saat mem-build aturan:
- Permintaan: Satu atau beberapa metode yang dipanggil dalam pernyataan
allow
. Ini adalah metode yang Anda izinkan untuk berjalan. Metode standarnya adalah:get
,list
,create
,update
, dandelete
. Metoderead
danwrite
yang praktis akan mengaktifkan akses baca dan tulis yang luas pada jalur database atau penyimpanan yang ditentukan. - Jalur: Lokasi database atau penyimpanan, direpresentasikan sebagai jalur URI.
- Aturan: Pernyataan
allow
, berisi kondisi yang mengizinkan permintaan jika kondisi tersebut bernilai benar.
Baca penjelasan selengkapnya mengenai setiap konsep tersebut di bawah.
Realtime Database
Pada Realtime Database, Aturan Keamanan Firebase terdiri dari ekspresi serupa JavaScript yang terdapat dalam dokumen JSON.
Aturan tersebut menggunakan sintaksis berikut:
{
"rules": {
"<<path>>": {
// Allow the request if the condition for each method is true.
".read": <<condition>>,
".write": <<condition>>,
".validate": <<condition>>
}
}
}
Aturan memiliki tiga elemen dasar, yaitu:
- Jalur: Lokasi database. Ini mencerminkan struktur JSON database Anda.
- Permintaan: Ini adalah metode yang digunakan aturan untuk memberikan akses. Aturan
read
danwrite
memberikan akses baca dan tulis yang luas, sedangkan aturanvalidate
bertindak sebagai verifikasi sekunder untuk memberikan akses berdasarkan data yang masuk atau yang sudah ada. - Kondisi: Kondisi yang mengizinkan permintaan jika kondisi tersebut bernilai benar.
Pembuatan aturan
Cloud Firestore
Berikut elemen dasar aturan di Cloud Firestore dan Cloud Storage:
- Deklarasi
service
: Mendeklarasikan pada produk Firebase apa aturan tersebut diterapkan. - Blok
match
: Menentukan jalur dalam database atau bucket penyimpanan tempat aturan tersebut diterapkan. - Pernyataan
allow
: Menentukan kondisi untuk memberikan akses, yang dibedakan berdasarkan metode. Metode yang didukung meliputi:get
,list
,create
,update
,delete
, dan metoderead
danwrite
yang praktis. - Deklarasi
function
opsional: Memberikan kemampuan untuk mengombinasikan dan menggabungkan kondisi untuk digunakan pada beberapa aturan.
service
berisi satu atau beberapa blok match
dengan pernyataan allow
yang
menetapkan kondisi yang memberikan akses ke permintaan. Variabel
request
dan resource
dapat diterapkan dalam kondisi 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
.
Service
Deklarasi service
menentukan pada produk atau layanan Firebase apa aturan
Anda diterapkan. 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
}
Cloud Storage
service firebase.storage {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Aturan yang ditetapkan untuk Cloud Firestore dan Cloud Storage menggunakan Firebase CLI harus disimpan dalam file terpisah.
Match
Blok match
mendeklarasikan pola path
yang dicocokkan dengan
jalur operasi yang diminta (request.path
yang masuk). Isi
match
harus memiliki satu atau beberapa blok match
bertingkat, pernyataan allow
,
atau deklarasi function
. Jalur dalam blok match
bertingkat bersifat relatif terhadap
jalur dalam blok match
induk.
Pola path
adalah nama serupa direktori yang dapat mengandung variabel atau
karakter pengganti. Dengan pola path
, pencocokan segmen jalur tunggal dan
segmen multi-jalur dapat dilakukan. Variabel apa pun yang terikat dengan path
terlihat dalam cakupan match
atau cakupan bertingkat tempat path
dideklarasikan.
Kecocokan dengan pola path
dapat bersifat sebagian atau penuh:
- Kecocokan sebagian: Awalan pola
path
cocok dengan awalanrequest.path
. - Kecocokan penuh: Pola
path
cocok dengan seluruhrequest.path
.
Jika ada kecocokan penuh, aturan dalam blok dievaluasi. Jika ada kecocokan sebagian, aturan match
bertingkat akan diuji untuk melihat apakah
path
bertingkat akan menghasilkan kecocokan penuh.
Aturan dalam setiap match
penuh dievaluasi untuk menentukan apakah
permintaan akan diizinkan atau tidak. Permintaan akan diizinkan jika aturan yang cocok
memberikan akses. Permintaan akan ditolak jika tidak ada aturan yang cocok yang memberikan akses.
// 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 ditunjukkan pada contoh di atas, deklarasi path
mendukung variabel
berikut:
- Karakter pengganti segmen tunggal: Variabel karakter pengganti dideklarasikan di jalur dengan mengapit variabel menggunakan kurung kurawal:
{variable}
. Variabel ini dapat diakses dalam pernyataanmatch
sebagaistring
. - Karakter pengganti berulang: Karakter pengganti berulang, atau multisegmen, cocok dengan beberapa segmen jalur pada atau di bawah jalur. Karakter pengganti ini cocok dengan semua jalur
di bawah lokasi yang ditentukan. Anda dapat mendeklarasikannya dengan menambahkan string
=**
di akhir variabel segmen:{variable=**}
. Variabel ini dapat diakses dalam pernyataanmatch
sebagai objekpath
.
Allow
Blok match
berisi satu atau beberapa pernyataan allow
. Pernyataan tersebut adalah aturan Anda
yang sebenarnya. Anda dapat menerapkan aturan allow
ke satu atau beberapa metode. Kondisi pada pernyataan allow
harus bernilai benar agar Cloud Firestore atau Cloud Storage dapat memberikan izin untuk setiap permintaan yang masuk. Anda juga dapat menulis pernyataan allow
tanpa kondisi, misalnya, allow read
. Namun, jika pernyataan allow
tidak menyertakan
kondisi, pernyataan tersebut akan selalu mengizinkan permintaan untuk metode tersebut.
Jika ada aturan allow
yang terpenuhi untuk metode tersebut, permintaan
akan diizinkan. Selain itu, jika ada aturan yang lebih luas yang memberikan akses, Aturan akan memberikan
akses dan mengabaikan aturan yang lebih terperinci yang mungkin membatasi akses.
Pertimbangkan contoh berikut, yang mengizinkan setiap pengguna untuk membaca atau menghapus file mereka sendiri. Aturan yang lebih terperinci hanya mengizinkan penulisan jika pengguna yang meminta penulisan adalah pemilik file dan file tersebut berformat PNG. Pengguna dapat menghapus semua file di subjalur — meskipun file tersebut tidak dalam format 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 praktis | |
read |
Semua jenis permintaan baca |
write |
Semua jenis permintaan tulis |
Metode standar | |
get |
Permintaan baca untuk dokumen atau file tunggal |
list |
Permintaan baca untuk kueri dan koleksi |
create |
Menulis dokumen atau file baru |
update |
Menulis ke dokumen database yang sudah ada atau memperbarui metadata file |
delete |
Menghapus data |
Anda tidak dapat menimpa metode baca di blok match
yang sama atau
metode tulis yang bertentangan dalam deklarasi path
yang sama.
Berikut contoh aturan yang 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 menjadi makin kompleks, Anda dapat menggabungkan kumpulan kondisi ke dalam fungsi yang dapat digunakan kembali di semua kumpulan aturan. Aturan keamanan mendukung fungsi kustom. Sintaksis untuk fungsi kustom mirip dengan JavaScript, tetapi fungsi aturan keamanan ditulis dalam bahasa khusus domain yang memiliki beberapa batasan penting:
- Fungsi hanya dapat berisi satu pernyataan
return
. Fungsi tidak boleh berisi logika lain apa pun. Misalnya, fungsi tidak dapat menjalankan loop atau memanggil layanan eksternal. - Fungsi dapat secara otomatis mengakses fungsi dan variabel dari cakupan
tempat ditetapkannya. Misalnya, fungsi yang ditetapkan ke dalam cakupan
service cloud.firestore
memiliki akses ke variabelresource
dan memiliki fungsi bawaan sepertiget()
danexists()
. - Fungsi dapat memanggil fungsi lain tetapi tidak dapat secara berulang. Total kedalaman stack panggilan dibatasi hingga 20.
- Dalam aturan versi
v2
, fungsi dapat menentukan variabel menggunakan kata kuncilet
. Fungsi dapat memiliki hingga 10 binding let, tetapi harus diakhiri dengan pernyataan return.
Fungsi ditetapkan dengan kata kunci function
dan menerima nol argumen atau lebih. Misalnya, Anda dapat 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 menampilkan argumen fungsi dan tugas let. Pernyataan tugas let harus dipisahkan dengan tanda titik koma.
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
Perhatikan cara tugas isAdmin
menerapkan pencarian koleksi admin. Untuk evaluasi lambat tanpa mengharuskan pencarian yang tidak diperlukan, manfaatkan kepraktisan dari perbandingan &&
(AND) dan ||
(OR) untuk memanggil fungsi kedua hanya jika isAuthor
ditampilkan dengan nilai true (benar) (untuk perbandingan &&
) atau false (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);
}
Dengan menggunakan fungsi, aturan keamanan akan lebih mudah dipertahankan seiring makin kompleksnya aturan.
Cloud Storage
Berikut elemen dasar aturan di Cloud Firestore dan Cloud Storage:
- Deklarasi
service
: Mendeklarasikan pada produk Firebase apa aturan tersebut diterapkan. - Blok
match
: Menentukan jalur dalam database atau bucket penyimpanan tempat aturan tersebut diterapkan. - Pernyataan
allow
: Menentukan kondisi untuk memberikan akses, yang dibedakan berdasarkan metode. Metode yang didukung meliputi:get
,list
,create
,update
,delete
, dan metoderead
danwrite
yang praktis. - Deklarasi
function
opsional: Memberikan kemampuan untuk mengombinasikan dan menggabungkan kondisi untuk digunakan pada beberapa aturan.
service
berisi satu atau beberapa blok match
dengan pernyataan allow
yang
menetapkan kondisi yang memberikan akses ke permintaan. Variabel
request
dan resource
dapat diterapkan dalam kondisi 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
.
Service
Deklarasi service
menentukan pada produk atau layanan Firebase apa aturan
Anda diterapkan. 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
}
Cloud Storage
service firebase.storage {
// Your 'match' blocks with their corresponding 'allow' statements and
// optional 'function' declarations are contained here
}
Aturan yang ditetapkan untuk Cloud Firestore dan Cloud Storage menggunakan Firebase CLI harus disimpan dalam file terpisah.
Match
Blok match
mendeklarasikan pola path
yang dicocokkan dengan
jalur operasi yang diminta (request.path
yang masuk). Isi
match
harus memiliki satu atau beberapa blok match
bertingkat, pernyataan allow
,
atau deklarasi function
. Jalur dalam blok match
bertingkat bersifat relatif terhadap
jalur dalam blok match
induk.
Pola path
adalah nama serupa direktori yang dapat mengandung variabel atau
karakter pengganti. Dengan pola path
, pencocokan segmen jalur tunggal dan
segmen multi-jalur dapat dilakukan. Variabel apa pun yang terikat dengan path
terlihat dalam cakupan match
atau cakupan bertingkat tempat path
dideklarasikan.
Kecocokan dengan pola path
dapat bersifat sebagian atau penuh:
- Kecocokan sebagian: Awalan pola
path
cocok dengan awalanrequest.path
. - Kecocokan penuh: Pola
path
cocok dengan seluruhrequest.path
.
Jika ada kecocokan penuh, aturan dalam blok dievaluasi. Jika ada kecocokan sebagian, aturan match
bertingkat akan diuji untuk melihat apakah
path
bertingkat akan menghasilkan kecocokan penuh.
Aturan dalam setiap match
penuh dievaluasi untuk menentukan apakah
permintaan akan diizinkan atau tidak. Permintaan akan diizinkan jika aturan yang cocok
memberikan akses. Permintaan akan ditolak jika tidak ada aturan yang cocok yang memberikan akses.
// 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 ditunjukkan pada contoh di atas, deklarasi path
mendukung variabel
berikut:
- Karakter pengganti segmen tunggal: Variabel karakter pengganti dideklarasikan di jalur dengan mengapit variabel menggunakan kurung kurawal:
{variable}
. Variabel ini dapat diakses dalam pernyataanmatch
sebagaistring
. - Karakter pengganti berulang: Karakter pengganti berulang, atau multisegmen, cocok dengan beberapa segmen jalur pada atau di bawah jalur. Karakter pengganti ini cocok dengan semua jalur
di bawah lokasi yang ditentukan. Anda dapat mendeklarasikannya dengan menambahkan string
=**
di akhir variabel segmen:{variable=**}
. Variabel ini dapat diakses dalam pernyataanmatch
sebagai objekpath
.
Allow
Blok match
berisi satu atau beberapa pernyataan allow
. Pernyataan tersebut adalah aturan Anda
yang sebenarnya. Anda dapat menerapkan aturan allow
ke satu atau beberapa metode. Kondisi pada pernyataan allow
harus bernilai benar agar Cloud Firestore atau Cloud Storage dapat memberikan izin untuk setiap permintaan yang masuk. Anda juga dapat menulis pernyataan allow
tanpa kondisi, misalnya, allow read
. Namun, jika pernyataan allow
tidak menyertakan
kondisi, pernyataan tersebut akan selalu mengizinkan permintaan untuk metode tersebut.
Jika ada aturan allow
yang terpenuhi untuk metode tersebut, permintaan
akan diizinkan. Selain itu, jika ada aturan yang lebih luas yang memberikan akses, Aturan akan memberikan
akses dan mengabaikan aturan yang lebih terperinci yang mungkin membatasi akses.
Pertimbangkan contoh berikut, yang mengizinkan setiap pengguna untuk membaca atau menghapus file mereka sendiri. Aturan yang lebih terperinci hanya mengizinkan penulisan jika pengguna yang meminta penulisan adalah pemilik file dan file tersebut berformat PNG. Pengguna dapat menghapus semua file di subjalur — meskipun file tersebut tidak dalam format 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 praktis | |
read |
Semua jenis permintaan baca |
write |
Semua jenis permintaan tulis |
Metode standar | |
get |
Permintaan baca untuk dokumen atau file tunggal |
list |
Permintaan baca untuk kueri dan koleksi |
create |
Menulis dokumen atau file baru |
update |
Menulis ke dokumen database yang sudah ada atau memperbarui metadata file |
delete |
Menghapus data |
Anda tidak dapat menimpa metode baca di blok match
yang sama atau
metode tulis yang bertentangan dalam deklarasi path
yang sama.
Berikut contoh aturan yang 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 menjadi makin kompleks, Anda dapat menggabungkan kumpulan kondisi ke dalam fungsi yang dapat digunakan kembali di semua kumpulan aturan. Aturan keamanan mendukung fungsi kustom. Sintaksis untuk fungsi kustom mirip dengan JavaScript, tetapi fungsi aturan keamanan ditulis dalam bahasa khusus domain yang memiliki beberapa batasan penting:
- Fungsi hanya dapat berisi satu pernyataan
return
. Fungsi tidak boleh berisi logika lain apa pun. Misalnya, fungsi tidak dapat menjalankan loop atau memanggil layanan eksternal. - Fungsi dapat secara otomatis mengakses fungsi dan variabel dari cakupan
tempat ditetapkannya. Misalnya, fungsi yang ditetapkan ke dalam cakupan
service cloud.firestore
memiliki akses ke variabelresource
dan memiliki fungsi bawaan sepertiget()
danexists()
. - Fungsi dapat memanggil fungsi lain tetapi tidak dapat secara berulang. Total kedalaman stack panggilan dibatasi hingga 20.
- Dalam aturan versi
v2
, fungsi dapat menentukan variabel menggunakan kata kuncilet
. Fungsi dapat memiliki hingga 10 binding let, tetapi harus diakhiri dengan pernyataan return.
Fungsi ditetapkan dengan kata kunci function
dan menerima nol argumen atau lebih. Misalnya, Anda dapat 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 menampilkan argumen fungsi dan tugas let. Pernyataan tugas let harus dipisahkan dengan tanda titik koma.
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
Perhatikan cara tugas isAdmin
menerapkan pencarian koleksi admin. Untuk evaluasi lambat tanpa mengharuskan pencarian yang tidak diperlukan, manfaatkan kepraktisan dari perbandingan &&
(AND) dan ||
(OR) untuk memanggil fungsi kedua hanya jika isAuthor
ditampilkan dengan nilai true (benar) (untuk perbandingan &&
) atau false (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);
}
Dengan menggunakan fungsi, aturan keamanan akan lebih mudah dipertahankan seiring makin kompleksnya aturan.
Realtime Database
Sebagaimana diuraikan di atas, Aturan Realtime Database mencakup tiga elemen dasar: lokasi database sebagai cerminan struktur JSON database, jenis permintaan, dan kondisi yang memberikan akses.
Lokasi database
Struktur aturan Anda harus mengikuti struktur data yang telah disimpan di database. Misalnya, pada aplikasi chat dengan daftar pesan, data yang Anda miliki akan terlihat seperti ini:
{
"messages": {
"message0": {
"content": "Hello",
"timestamp": 1405704370369
},
"message1": {
"content": "Goodbye",
"timestamp": 1405704395231
},
...
}
}
Aturan yang dibuat harus mencerminkan struktur tersebut. 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 dicontohkan di atas, Aturan Realtime Database mendukung variabel $location
untuk mencocokkan segmen jalur. Gunakan awalan $
di depan segmen jalur
untuk mencocokkan aturan dengan node turunan 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 bersamaan dengan
nama jalur tetap.
{
"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
Ada tiga jenis aturan pada Realtime Database. Dua dari jenis aturan ini —
read
dan write
— berlaku pada metode permintaan masuk. Jenis aturan validate
menerapkan struktur data dan memvalidasi format serta isi data.
Aturan menjalankan aturan .validate
setelah memverifikasi bahwa aturan .write
telah memberikan akses.
Jenis Aturan | |
---|---|
.read | Menjelaskan apakah dan kapan data boleh dibaca oleh pengguna. |
.write | Menjelaskan apakah dan kapan data boleh ditulis. |
.validate | Menentukan tampilan nilai yang diformat dengan benar, apakah nilai memiliki atribut turunan, dan tipe data. |
Secara default, jika tidak ada aturan yang mengizinkannya, akses di jalur akan ditolak.
Mem-build kondisi
Cloud Firestore
Kondisi adalah ekspresi boolean yang menentukan
diizinkannya atau ditolaknya operasi tertentu. Variabel request
dan resource
memberikan konteks untuk kondisi tersebut.
Variabel request
Variabel request
mencakup kolom dan informasi terkait berikut ini:
request.auth
Token Web JSON (JWT) yang berisi kredensial autentikasi dari Firebase Authentication. Token auth
berisi kumpulan klaim standar dan klaim
khusus yang dibuat melalui Firebase Authentication. Pelajari
Aturan Keamanan Firebase dan Authentication lebih lanjut.
request.method
request.method
dapat berupa metode standar atau metode kustom. Metode
read
dan write
yang praktis juga dapat digunakan untuk menyederhanakan penulisan aturan yang
berlaku untuk semua metode standar hanya baca atau hanya tulis.
request.params
request.params
menyertakan semua data yang tidak secara spesifik terkait dengan
request.resource
yang mungkin berguna untuk proses evaluasi. Dalam praktiknya, peta ini
harus kosong untuk semua metode standar, dan harus berisi data non-resource
untuk metode kustom. Layanan harus berhati-hati agar tidak mengganti nama atau mengubah jenis
kunci dan nilai apa pun yang ditampilkan sebagai params.
request.path
request.path
adalah jalur untuk resource
target. Jalur tersebut bersifat relatif
terhadap layanan. Segmen jalur yang berisi karakter aman non-URL seperti /
dienkode dengan URL.
Variabel resource
Variabel resource
adalah nilai saat ini di dalam layanan yang ditampilkan sebagai peta
key-value pair. Mereferensikan resource
dalam suatu kondisi akan menghasilkan
maksimal satu pembacaan nilai dari layanan. Pencarian ini akan diperhitungkan terhadap kuota terkait layanan untuk resource. Untuk permintaan get
, resource
hanya akan
memperhitungkan kuota penolakan.
Operator dan prioritas operator
Gunakan tabel di bawah sebagai referensi untuk operator dan prioritasnya yang sesuai pada Aturan untuk Cloud Firestore dan Cloud Storage.
Ekspresi arbitrer tertentu a
dan b
, kolom f
, dan indeks i
.
Operator | Deskripsi | Asosiativitas |
---|---|---|
a[i] a() a.f |
Akses indeks, panggilan, kolom | kiri ke kanan |
!a -a |
Negasi unary | kanan ke kiri |
a/b a%b a*b |
Operator multiplikatif | kiri ke kanan |
a+b a-b |
Operator aditif | kiri ke kanan |
a>b a>=b a<=b |
Operator relasional | kiri ke kanan |
a in b |
Keberadaan dalam daftar atau peta | kiri ke kanan |
a is type |
Perbandingan jenis, dengan type dapat berupa bool, int, float, angka, string, daftar, peta, stempel waktu, durasi, jalur, atau latlng |
kiri ke kanan |
a==b a!=b |
Operator perbandingan | kiri ke kanan |
a && b |
AND kondisional | kiri ke kanan |
a || b |
OR kondisional | kiri ke kanan |
a ? true_value : false_value |
Ekspresi ternary | kiri ke kanan |
Cloud Storage
Kondisi adalah ekspresi boolean yang menentukan
diizinkannya atau ditolaknya operasi tertentu. Variabel request
dan resource
memberikan konteks untuk kondisi tersebut.
Variabel request
Variabel request
mencakup kolom dan informasi terkait berikut ini:
request.auth
Token Web JSON (JWT) yang berisi kredensial autentikasi dari Firebase Authentication. Token auth
berisi kumpulan klaim standar dan klaim
khusus yang dibuat melalui Firebase Authentication. Pelajari
Aturan Keamanan Firebase dan Authentication lebih lanjut.
request.method
request.method
dapat berupa metode standar atau metode kustom. Metode
read
dan write
yang praktis juga dapat digunakan untuk menyederhanakan penulisan aturan yang
berlaku untuk semua metode standar hanya baca atau hanya tulis.
request.params
request.params
menyertakan semua data yang tidak secara spesifik terkait dengan
request.resource
yang mungkin berguna untuk proses evaluasi. Dalam praktiknya, peta ini
harus kosong untuk semua metode standar, dan harus berisi data non-resource
untuk metode kustom. Layanan harus berhati-hati agar tidak mengganti nama atau mengubah jenis
kunci dan nilai apa pun yang ditampilkan sebagai params.
request.path
request.path
adalah jalur untuk resource
target. Jalur tersebut bersifat relatif
terhadap layanan. Segmen jalur yang berisi karakter aman non-URL seperti /
dienkode dengan URL.
Variabel resource
Variabel resource
adalah nilai saat ini di dalam layanan yang ditampilkan sebagai peta
key-value pair. Mereferensikan resource
dalam suatu kondisi akan menghasilkan
maksimal satu pembacaan nilai dari layanan. Pencarian ini akan diperhitungkan terhadap kuota terkait layanan untuk resource. Untuk permintaan get
, resource
hanya akan
memperhitungkan kuota penolakan.
Operator dan prioritas operator
Gunakan tabel di bawah sebagai referensi untuk operator dan prioritasnya yang sesuai pada Aturan untuk Cloud Firestore dan Cloud Storage.
Ekspresi arbitrer tertentu a
dan b
, kolom f
, dan indeks i
.
Operator | Deskripsi | Asosiativitas |
---|---|---|
a[i] a() a.f |
Akses indeks, panggilan, kolom | kiri ke kanan |
!a -a |
Negasi unary | kanan ke kiri |
a/b a%b a*b |
Operator multiplikatif | kiri ke kanan |
a+b a-b |
Operator aditif | kiri ke kanan |
a>b a>=b a<=b |
Operator relasional | kiri ke kanan |
a in b |
Keberadaan dalam daftar atau peta | kiri ke kanan |
a is type |
Perbandingan jenis, dengan type dapat berupa bool, int, float, angka, string, daftar, peta, stempel waktu, durasi, jalur, atau latlng |
kiri ke kanan |
a==b a!=b |
Operator perbandingan | kiri ke kanan |
a && b |
AND kondisional | kiri ke kanan |
a || b |
OR kondisional | kiri ke kanan |
a ? true_value : false_value |
Ekspresi ternary | kiri ke kanan |
Realtime Database
Kondisi adalah ekspresi boolean yang menentukan diizinkannya atau ditolaknya operasi tertentu. Anda dapat menentukan kondisi tersebut pada Aturan Realtime Database dengan cara berikut.
Variabel yang telah ditetapkan
Ada sejumlah variabel bermanfaat yang telah ditetapkan, yang dapat diakses di dalam definisi aturan. Berikut adalah ringkasan dari setiap variabel tersebut:
Variabel yang Telah Ditetapkan | |
---|---|
now | Waktu saat ini dalam satuan milidetik sejak epoch Linux. Variabel ini bekerja dengan baik terutama untuk memvalidasi stempel waktu yang dibuat dengan firebase.database.ServerValue.TIMESTAMP SDK. |
root | RuleDataSnapshot yang mewakili keadaan jalur root di database Firebase sebelum percobaan pengoperasian. |
newData | RuleDataSnapshot yang mewakili keadaan data setelah percobaan pengoperasian. Variabel ini mencakup data baru yang sedang ditulis dan data yang sudah ada. |
data | RuleDataSnapshot yang mewakili keadaan data sebelum percobaan pengoperasian. |
$ variables | Jalur karakter pengganti yang digunakan untuk mewakili ID dan kunci turunan dinamis. |
auth | Mewakili payload token pengguna yang telah diautentikasi. |
Variabel ini bisa digunakan di mana saja dalam aturan Anda. Misalnya, aturan
keamanan di bawah memastikan bahwa data yang ditulis ke node /foo/
harus berupa string
sepanjang 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
Setiap data pada database Anda dapat digunakan dalam aturan Anda. Dengan menggunakan variabel
root
, data
, dan newData
yang telah ditetapkan, Anda dapat mengakses setiap jalur sebagaimana adanya sebelum atau setelah peristiwa tulis.
Pertimbangkan contoh ini, yang memungkinkan operasi tulis selama nilai node /allow_writes/
adalah true
, node induk tidak memiliki flag readOnly
yang ditetapkan, dan terdapat turunan 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 tidak dapat menggunakan aturan sebagai filter, Anda dapat membatasi akses ke subkumpulan data
dengan menggunakan parameter kueri dalam aturan. Gunakan ekspresi query.
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 yang ada di koleksi baskets
hanya bagi keranjang belanja milik pengguna aktif:
"baskets": {
".read": "auth.uid !== null &&
query.orderByChild === 'owner' &&
query.equalTo === auth.uid" // restrict basket access to owner of basket
}
Kueri berikut, yang mencakup parameter kueri dalam aturan, akan berhasil diterapkan:
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 error PermissionDenied
:
db.ref("baskets").on("value", cb) // Would fail with PermissionDenied
Anda juga dapat menggunakan aturan berbasis kueri untuk membatasi jumlah data yang didownload klien melalui operasi baca.
Misalnya, aturan berikut membatasi akses baca hanya untuk 1.000 hasil kueri pertama, 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)
Ekspresi query.
berikut tersedia di Aturan Keamanan Realtime Database.
Ekspresi aturan berbasis kueri | ||
---|---|---|
Ekspresi | Jenis | Deskripsi |
query.orderByKey query.orderByPriority query.orderByValue |
boolean | Benar untuk kueri yang diurutkan berdasarkan kunci, prioritas, atau nilai. Salah untuk kueri yang tidak diurutkan. |
query.orderByChild | string null |
Gunakan string untuk mewakili jalur relatif ke node turunan. Misalnya,
query.orderByChild === "address/zip" . Jika kueri tidak diurutkan berdasarkan node turunan, nilai ini adalah null.
|
query.startAt query.endAt query.equalTo |
string number boolean null |
Mengambil ikatan kueri yang mengeksekusi, atau menampilkan null jika tidak ada ikatan yang ditetapkan. |
query.limitToFirst query.limitToLast |
number null |
Mengambil batasan kueri pelaksana, atau menampilkan null jika tidak ada batasan 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.
Membuat kondisi
Kondisi sebenarnya akan bervariasi berdasarkan akses yang ingin Anda berikan. Aturan sengaja menawarkan tingkat fleksibilitas yang sangat besar, sehingga aturan aplikasi Anda pada akhirnya bisa sesederhana atau serumit yang Anda inginkan.
Untuk mengetahui panduan cara membuat Aturan siap produksi yang sederhana, lihat Aturan Keamanan Dasar.