Panduan ini dikembangkan dari panduan mempelajari sintaksis inti bahasa Firebase Security Rules untuk menunjukkan cara menambahkan kondisi ke Firebase Security Rules untuk Cloud Storage.
Elemen penyusun utama Cloud Storage Security Rules adalah kondisi.
Kondisi adalah ekspresi boolean yang menentukan apakah operasi tertentu
diizinkan atau ditolak. Untuk aturan dasar, penggunaan literal true
dan false
sebagai kondisi berfungsi dengan sangat baik. Namun, bahasa Firebase Security Rules untuk Cloud Storage memberi Anda cara untuk menulis kondisi yang lebih kompleks yang dapat:
- Memeriksa autentikasi pengguna
- Memvalidasi data yang masuk
Autentikasi
Firebase Security Rules untuk Cloud Storage terintegrasi dengan Firebase Authentication untuk menyediakan autentikasi berbasis pengguna yang andal untuk Cloud Storage. Hal ini memungkinkan kontrol akses terperinci berdasarkan klaim token Firebase Authentication.
Saat pengguna terautentikasi membuat permintaan ke Cloud Storage,
variabel request.auth
akan diisi dengan uid
(request.auth.uid
) pengguna serta klaim JWT Firebase Authentication (request.auth.token
).
Selain itu, saat menggunakan autentikasi kustom, klaim tambahan akan muncul
di kolom request.auth.token
.
Saat pengguna tanpa autentikasi membuat permintaan, variabel request.auth
adalah
null
.
Dengan menggunakan data ini, ada beberapa cara umum menggunakan autentikasi untuk mengamankan file:
- Publik: abaikan
request.auth
- Pribadi terautentikasi: pastikan
request.auth
bukannull
- Pribadi pengguna: pastikan
request.auth.uid
sama dengan jaluruid
- Pribadi grup: pastikan klaim token kustom cocok dengan klaim yang dipilih, atau baca metadata file untuk melihat apakah ada kolom metadata atau tidak
Publik
Setiap aturan yang tidak mempertimbangkan konteks request.auth
dapat dianggap sebagai
aturan public
, karena tidak mempertimbangkan konteks autentikasi pengguna.
Aturan ini dapat berguna untuk menampilkan data publik seperti aset game, file suara,
atau konten statis lainnya.
// Anyone to read a public image if the file is less than 100kB // Anyone can upload a public file ending in '.txt' match /public/{imageId} { allow read: if resource.size < 100 * 1024; allow write: if imageId.matches(".*\\.txt"); }
Pribadi terautentikasi
Dalam kasus tertentu, Anda mungkin ingin agar data dapat dilihat oleh semua pengguna aplikasi yang terautentikasi,
tetapi tidak oleh pengguna tanpa autentikasi. Karena variabel request.auth
adalah null
untuk semua pengguna tanpa autentikasi, Anda hanya perlu memastikan bahwa
variabel request.auth
ada untuk mengharuskan autentikasi:
// Require authentication on all internal image reads match /internal/{imageId} { allow read: if request.auth != null; }
Pengguna pribadi
Sejauh ini, kasus penggunaan request.auth
yang paling umum adalah memberikan
izin terperinci kepada pengguna individual untuk mengakses file mereka: mulai dari mengupload gambar profil
hingga membaca dokumen pribadi.
Karena file di Cloud Storage memiliki "jalur" lengkap ke file, yang diperlukan untuk membuat file dikontrol oleh pengguna adalah bagian dari informasi identifikasi pengguna yang unik pada awalan nama file (seperti uid
pengguna) yang dapat diperiksa saat aturan dievaluasi:
// Only a user can upload their profile picture, but anyone can view it match /users/{userId}/profilePicture.png { allow read; allow write: if request.auth.uid == userId; }
Grup pribadi
Kasus penggunaan umum lainnya adalah memberikan izin grup pada suatu objek, seperti mengizinkan beberapa anggota tim untuk berkolaborasi pada dokumen bersama. Ada beberapa pendekatan untuk melakukan hal ini:
- Membuat token kustom Firebase Authentication yang berisi informasi tambahan tentang anggota grup (seperti ID grup)
- Menyertakan informasi grup (seperti ID grup atau daftar
uid
yang diberi otorisasi) di metadata file
Setelah disimpan dalam token atau metadata file, data ini dapat direferensikan dari dalam aturan:
// Allow reads if the group ID in your token matches the file metadata's `owner` property // Allow writes if the group ID is in the user's custom token match /files/{groupId}/{fileName} { allow read: if resource.metadata.owner == request.auth.token.groupId; allow write: if request.auth.token.groupId == groupId; }
Evaluasi Permintaan
Upload, download, perubahan metadata, dan penghapusan dievaluasi menggunakan request
dikirim ke Cloud Storage. Selain ID unik pengguna dan payload Firebase Authentication di objek request.auth
seperti yang dideskripsikan di atas, variabel request
berisi jalur file tempat permintaan akan dijalankan, waktu saat permintaan diterima, dan nilai resource
baru jika permintaan tersebut adalah permintaan tulis.
Objek request
juga berisi ID unik pengguna dan payload Firebase Authentication di objek request.auth
yang akan dijelaskan lebih lanjut di bagian Keamanan Berbasis Pengguna dalam dokumentasi.
Daftar lengkap properti di objek request
tersedia di bawah:
Properti | Jenis | Deskripsi |
---|---|---|
auth |
map<string, string> | Saat pengguna login, memberikan uid , ID unik pengguna, dan token , peta klaim JWT Firebase Authentication. Jika pengguna tidak login, nilainya adalah null . |
params |
map<string, string> | Peta yang memuat parameter kueri permintaan. |
path |
jalur | path yang mewakili jalur tempat permintaan
dijalankan. |
resource |
map<string, string> | Nilai resource baru, hanya ada pada permintaan write .
|
time |
timestamp | Stempel waktu yang menunjukkan waktu server ketika permintaan dievaluasi. |
Evaluasi Resource
Saat mengevaluasi aturan, Anda mungkin juga ingin mengevaluasi metadata dari file yang diupload, didownload, diubah, atau dihapus. Dengan begitu, Anda dapat membuat aturan yang rumit dan kuat untuk melakukan hal spesifik, seperti hanya mengizinkan upload file dengan jenis konten tertentu atau penghapusan file dengan ukuran lebih besar dari ukuran tertentu.
Firebase Security Rules untuk Cloud Storage memberikan metadata file di objek resource
, yang berisi key-value pair dari metadata yang muncul pada objek Cloud Storage. Properti ini dapat diinspeksi pada permintaan read
atau write
untuk memastikan integritas data.
Pada permintaan write
(seperti upload, pembaruan metadata, dan penghapusan),
selain objek resource
, yang berisi metadata file untuk file
yang saat ini ada di jalur permintaan, Anda juga dapat menggunakan objek
request.resource
, yang berisi subset metadata file yang
akan ditulis jika operasi tulis diizinkan. Anda dapat menggunakan kedua nilai tersebut untuk
memastikan integritas data atau memberlakukan pembatasan aplikasi, seperti jenis atau ukuran file.
Daftar lengkap properti di objek resource
tersedia di bawah:
Properti | Jenis | Deskripsi |
---|---|---|
name |
string | Nama lengkap objek |
bucket |
string | Nama bucket yang ditempati objek ini. |
generation |
int | Google Cloud Storage object generation dari objek ini. |
metageneration |
int | Google Cloud Storage object metageneration dari objek ini. |
size |
int | Ukuran objek, dalam byte. |
timeCreated |
timestamp | Stempel waktu yang menunjukkan kapan objek dibuat. |
updated |
timestamp | Stempel waktu yang menunjukkan kapan objek terakhir diperbarui. |
md5Hash |
string | Hash MD5 untuk objek ini. |
crc32c |
string | Hash crc32c untuk objek ini. |
etag |
string | Etag yang terkait dengan objek ini. |
contentDisposition |
string | Disposisi konten yang terkait dengan objek ini. |
contentEncoding |
string | Encoding konten yang terkait dengan objek ini. |
contentLanguage |
string | Bahasa konten yang terkait dengan objek ini. |
contentType |
string | Jenis konten yang terkait dengan objek ini. |
metadata |
map<string, string> | Key-value pair untuk metadata kustom tambahan yang ditetapkan developer. |
request.resource
berisi semua properti di atas kecuali generation
, metageneration
, etag
, timeCreated
, dan updated
.
Melakukan peningkatan dengan Cloud Firestore
Anda dapat mengakses dokumen di Cloud Firestore untuk mengevaluasi kriteria otorisasi lainnya.
Dengan menggunakan fungsi firestore.get()
dan firestore.exists()
, aturan keamanan Anda dapat mengevaluasi permintaan yang masuk berdasarkan dokumen di Cloud Firestore.
Fungsi firestore.get()
dan firestore.exists()
sama-sama memerlukan jalur dokumen yang ditentukan secara lengkap. Ketika menggunakan variabel untuk membuat jalur bagi firestore.get()
dan firestore.exists()
, Anda harus meng-escape variabel secara eksplisit menggunakan sintaksis $(variable)
.
Pada contoh di bawah, kita melihat aturan yang membatasi akses baca ke file kepada pengguna yang merupakan anggota klub tertentu.
service firebase.storage { match /b/{bucket}/o { match /users/{club}/files/{fileId} { allow read: if club in firestore.get(/databases/(default)/documents/users/$(request.auth.id)).memberships } } }
service firebase.storage { match /b/{bucket}/o { match /users/{userId}/photos/{fileId} { allow read: if firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.id)) } } }
Setelah membuat dan menyimpan Cloud Storage Security Rules pertama Anda yang menggunakan fungsi Cloud Firestore ini, Anda akan diminta di Firebase console atau Firebase CLI untuk mengaktifkan izin guna menghubungkan kedua produk.
Anda dapat menonaktifkan fitur ini dengan menghapus peran IAM, seperti yang dijelaskan dalam Mengelola dan men-deploy Firebase Security Rules.
Memvalidasi data
Firebase Security Rules untuk Cloud Storage juga dapat digunakan untuk validasi data, termasuk memvalidasi nama dan jalur file serta properti metadata file seperti contentType
dan size
.
service firebase.storage { match /b/{bucket}/o { match /images/{imageId} { // Only allow uploads of any image file that's less than 5MB allow write: if request.resource.size < 5 * 1024 * 1024 && request.resource.contentType.matches('image/.*'); } } }
Fungsi kustom
Seiring Firebase Security Rules Anda bertambah kompleks, Anda mungkin ingin mengemas kumpulan kondisi ke dalam fungsi yang dapat digunakan kembali di semua kumpulan aturan Anda. Aturan keamanan mendukung fungsi kustom. Sintaksis untuk fungsi kustom mirip dengan JavaScript, tetapi fungsi Firebase Security Rules 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 firebase.storage
memiliki akses ke variabelresource
, dan khusus Cloud Firestore, memiliki fungsi bawaan sepertiget()
danexists()
. - Sebuah fungsi dapat memanggil fungsi lain namun tidak secara berulang. Total kedalaman stack panggilan dibatasi sampai 10.
- Pada versi
rules2
, fungsi dapat menentukan variabel menggunakan kata kuncilet
. Fungsi dapat memiliki berapa pun binding let, tetapi harus diakhiri dengan pernyataan return.
Fungsi ditetapkan dengan kata kunci function
dan menerima nol argumen atau
lebih. Misalnya, Anda mungkin ingin menggabungkan dua jenis kondisi yang digunakan dalam contoh di atas menjadi sebuah fungsi:
service firebase.storage {
match /b/{bucket}/o {
// 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 /images/{imageId} {
allow read, write: if signedInOrPublic();
}
match /mp3s/{mp3Ids} {
allow read: if signedInOrPublic();
}
}
}
Dengan menggunakan fungsi di Firebase Security Rules, aturan akan lebih mudah dipertahankan seiring semakin kompleksnya aturan Anda.
Langkah berikutnya
Setelah membaca pembahasan kondisi di atas, Anda telah memiliki pemahaman yang lebih mendalam tentang Aturan dan siap untuk:
Mempelajari cara menangani kasus penggunaan inti, dan mempelajari alur kerja untuk mengembangkan, menguji, dan men-deploy Aturan:
- Menulis aturan yang menangani skenario umum.
- Mengembangkan pengetahuan dengan meninjau situasi saat Anda harus menemukan dan menghindari Aturan yang tidak aman.
- Menguji aturan menggunakan emulator Cloud Storage dan library pengujian Aturan Keamanan khusus.
- Meninjau metode yang tersedia untuk men-deploy Rules.