Validasi data

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
Catatan: Produk Firebase ini tidak tersedia di target App Clip.
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
Catatan: Produk Firebase ini tidak tersedia di target App Clip.
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.