Anda dapat menggunakan Aturan Keamanan Firebase untuk secara kondisional menulis data baru berdasarkan data yang ada di database atau bucket penyimpanan Anda. Anda juga dapat menulis aturan yang memberlakukan validasi data dengan membatasi penulisan berdasarkan data baru yang ditulis. Baca selengkapnya untuk mempelajari lebih lanjut tentang aturan yang menggunakan data yang ada untuk menciptakan kondisi keamanan.
Pilih produk di setiap bagian untuk mempelajari aturan validasi data lebih lanjut.
Batasan pada data baru
Cloud Firestore
Jika ingin memastikan bahwa dokumen yang berisi kolom tertentu
tidak dibuat, Anda dapat menyertakan kolom tersebut pada kondisi allow
. Misalnya, jika Anda
ingin menolak pembuatan dokumen apa pun yang berisi kolom ranking
,
Anda dapat melarangnya dalam kondisi create
.
service cloud.firestore {
match /databases/{database}/documents {
// Disallow
match /cities/{city} {
allow create: if !("ranking" in request.resource.data)
}
}
}
Realtime Database
Jika ingin memastikan bahwa data yang berisi nilai tertentu tidak ditambahkan
ke database, Anda dapat memasukkan nilai tersebut pada aturan dan
melarang penulisannya. Misalnya, jika Anda ingin menolak penulisan apa pun yang berisi nilai ranking
,
Anda dapat melarang penulisan pada dokumen apa pun dengan nilai ranking
.
{
"rules": {
// Write is allowed for all paths
".write": true,
// Allows writes only if new data doesn't include a `ranking` child value
".validate": "!newData.hasChild('ranking')
}
}
Cloud Storage
Jika ingin memastikan bahwa file yang berisi metadata tertentu tidak dibuat,
Anda dapat memasukkan metadata tersebut pada kondisi allow
. Misalnya, jika
Anda ingin menolak pembuatan file apa pun yang berisi metadata ranking
,
Anda dapat melarangnya dalam kondisi create
.
service firebase.storage {
match /b/{bucket}/o {
match /files/{allFiles=**} {
// Disallow
allow create: if !("ranking" in request.resource.metadata)
}
}
}
Menggunakan data yang ada pada Aturan Keamanan Firebase
Cloud Firestore
Banyak aplikasi yang menyimpan informasi kontrol akses sebagai kolom pada dokumen di database. Aturan Keamanan Cloud Firestore dapat mengizinkan atau menolak akses secara dinamis berdasarkan data dokumen:
service cloud.firestore {
match /databases/{database}/documents {
// Allow the user to read data if the document has the 'visibility'
// field set to 'public'
match /cities/{city} {
allow read: if resource.data.visibility == 'public';
}
}
}
Variabel resource
mengacu pada dokumen yang diminta, dan resource.data
adalah peta dari semua kolom dan nilai yang tersimpan di dokumen tersebut. Untuk informasi lebih lanjut tentang variabel resource
, lihat
dokumentasi referensi.
Ketika menulis data, Anda mungkin ingin membandingkan data yang masuk dengan data yang ada. Hal ini
memungkinkan Anda melakukan hal-hal seperti memastikan kolom tidak berubah,
kolom hanya bertambah satu, atau nilai baru berada setidaknya satu minggu di depan.
Dalam hal ini, jika kumpulan aturan Anda mengizinkan penulisan tertunda, variabel request.resource
akan memuat status waktu mendatang dari dokumen tersebut. Untuk operasi update
yang hanya mengubah sub-kumpulan kolom dokumen, variabel request.resource
akan memuat status dokumen tertunda setelah pengoperasian. Anda dapat memeriksa nilai kolom ini di request.resource
untuk mencegah pembaruan data yang tidak diinginkan atau tidak konsisten:
service cloud.firestore {
match /databases/{database}/documents {
// Make sure all cities have a positive population and
// the name is not changed
match /cities/{city} {
allow update: if request.resource.data.population > 0
&& request.resource.data.name == resource.data.name;
}
}
}
Realtime Database
Pada Realtime Database, gunakan aturan .validate
untuk menerapkan struktur data serta memvalidasi
format dan isi data. Aturan .validate
dijalankan setelah
memastikan aturan .write
memberikan akses.
Aturan .validate
tidak bersifat menurun. Jika ada aturan validasi yang gagal
pada jalur atau subjalur mana pun di dalam aturan, seluruh operasi penulisan akan ditolak.
Selain itu, definisi validasi hanya memeriksa nilai selain null, dan kemudian
mengabaikan semua permintaan yang menghapus data.
Perhatikan aturan .validate
berikut:
{
"rules": {
// write is allowed for all paths
".write": true,
"widget": {
// a valid widget must have attributes "color" and "size"
// allows deleting widgets (since .validate is not applied to delete rules)
".validate": "newData.hasChildren(['color', 'size'])",
"size": {
// the value of "size" must be a number between 0 and 99
".validate": "newData.isNumber() &&
newData.val() >= 0 &&
newData.val() <= 99"
},
"color": {
// the value of "color" must exist as a key in our mythical
// /valid_colors/ index
".validate": "root.child('valid_colors/' + newData.val()).exists()"
}
}
}
}
Permintaan tulis ke database dengan aturan di atas akan memiliki hasil sebagai berikut:
JavaScript
var ref = db.ref("/widget"); // PERMISSION_DENIED: does not have children color and size ref.set('foo'); // PERMISSION DENIED: does not have child color ref.set({size: 22}); // PERMISSION_DENIED: size is not a number ref.set({ size: 'foo', color: 'red' }); // SUCCESS (assuming 'blue' appears in our colors list) ref.set({ size: 21, color: 'blue'}); // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate ref.child('size').set(99);
Objective-C
FIRDatabaseReference *ref = [[[FIRDatabase database] reference] child: @"widget"]; // PERMISSION_DENIED: does not have children color and size [ref setValue: @"foo"]; // PERMISSION DENIED: does not have child color [ref setValue: @{ @"size": @"foo" }]; // PERMISSION_DENIED: size is not a number [ref setValue: @{ @"size": @"foo", @"color": @"red" }]; // SUCCESS (assuming 'blue' appears in our colors list) [ref setValue: @{ @"size": @21, @"color": @"blue" }]; // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate [[ref child:@"size"] setValue: @99];
Swift
var ref = FIRDatabase.database().reference().child("widget") // PERMISSION_DENIED: does not have children color and size ref.setValue("foo") // PERMISSION DENIED: does not have child color ref.setValue(["size": "foo"]) // PERMISSION_DENIED: size is not a number ref.setValue(["size": "foo", "color": "red"]) // SUCCESS (assuming 'blue' appears in our colors list) ref.setValue(["size": 21, "color": "blue"]) // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate ref.child("size").setValue(99);
Java
FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference ref = database.getReference("widget"); // PERMISSION_DENIED: does not have children color and size ref.setValue("foo"); // PERMISSION DENIED: does not have child color ref.child("size").setValue(22); // PERMISSION_DENIED: size is not a number Map<String,Object> map = new HashMap<String, Object>(); map.put("size","foo"); map.put("color","red"); ref.setValue(map); // SUCCESS (assuming 'blue' appears in our colors list) map = new HashMap<String, Object>(); map.put("size", 21); map.put("color","blue"); ref.setValue(map); // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate ref.child("size").setValue(99);
REST
# PERMISSION_DENIED: does not have children color and size curl -X PUT -d 'foo' \ https://docs-examples.firebaseio.com/rest/securing-data/example.json # PERMISSION DENIED: does not have child color curl -X PUT -d '{"size": 22}' \ https://docs-examples.firebaseio.com/rest/securing-data/example.json # PERMISSION_DENIED: size is not a number curl -X PUT -d '{"size": "foo", "color": "red"}' \ https://docs-examples.firebaseio.com/rest/securing-data/example.json # SUCCESS (assuming 'blue' appears in our colors list) curl -X PUT -d '{"size": 21, "color": "blue"}' \ https://docs-examples.firebaseio.com/rest/securing-data/example.json # If the record already exists and has a color, this will # succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) # will fail to validate curl -X PUT -d '99' \ https://docs-examples.firebaseio.com/rest/securing-data/example/size.json
Cloud Storage
Saat mengevaluasi aturan, sebaiknya Anda juga mengevaluasi metadata 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.
Objek resource
berisi key-value pair dengan metadata file yang muncul di objek Cloud Storage. Properti ini dapat diinspeksi pada permintaan read
atau
write
untuk memastikan integritas data. Objek resource
memeriksa metadata pada file yang sudah ada di bucket Cloud Storage Anda.
service firebase.storage {
match /b/{bucket}/o {
match /images {
match /{allImages=**} {
// Allow reads if a custom 'visibility' field is set to 'public'
allow read: if resource.metadata.visibility == 'public';
}
}
}
}
Anda juga dapat menggunakan objek request.resource
pada permintaan write
(seperti upload,
pembaruan metadata, dan penghapusan). Objek request.resource
mendapatkan
metadata dari file yang akan ditulis jika write
telah diizinkan.
Anda dapat menggunakan kedua nilai tersebut untuk mencegah pembaruan yang tidak diinginkan atau tidak konsisten, atau menerapkan batasan aplikasi, seperti jenis atau ukuran file.
service firebase.storage {
match /b/{bucket}/o {
match /images {
// Cascade read to any image type at any path
match /{allImages=**} {
allow read;
}
// Allow write files to the path "images/*", subject to the constraints:
// 1) File is less than 5MB
// 2) Content type is an image
// 3) Uploaded content type matches existing content type
// 4) File name (stored in imageId wildcard variable) is less than 32 characters
match /{imageId} {
allow write: if request.resource.size < 5 * 1024 * 1024
&& request.resource.contentType.matches('image/.*')
&& request.resource.contentType == resource.contentType
&& imageId.size() < 32
}
}
}
}
Daftar lengkap properti pada objek resource
tersedia dalam dokumentasi referensi.