Validasi Masukan

Whitelisting, filter_var, dan prinsip tidak memercayai apa pun.

Daftar isi

Validasi masukan adalah pemeriksaan bentuk dan isi data dari luar program sebelum data dipakai, dan prinsip dasarnya adalah tidak memercayai apa pun yang datang dari luar. Topik ini membahas pola whitelist untuk nilai-nilai tetap, fungsi filter_var untuk format umum, dan ctype_digit untuk pemeriksaan tingkat karakter. Setelah membacanya, setiap masukan dapat dipetakan ke pemeriksaan yang tepat sebelum menyentuh basis data atau keluaran.

Prinsip tidak memercayai masukan#

Data yang masuk melalui $_GET, $_POST, $_COOKIE, header permintaan, dan berkas unggahan semuanya dapat diubah oleh pengirimnya, sehingga tidak ada satu pun yang boleh dibaca lalu dipercaya begitu saja. Validasi di browser dengan atribut required atau type="email" hanyalah kenyamanan bagi pengunjung yang sah, karena permintaan dapat dikirim langsung ke server tanpa browser sama sekali. Pemeriksaan yang menentukan selalu berada di server.

Dua pendekatan validasi berbanding terbalik. Blacklist menyaring nilai-nilai yang dilarang dan selalu tertinggal, karena variasi masukan berbahaya lebih banyak daripada daftar yang mampu disusun. Whitelist bekerja sebaliknya, yaitu menetapkan nilai-nilai yang diizinkan lalu menolak sisanya secara otomatis, sehingga cocok untuk pilihan yang jumlahnya tetap seperti kolom pengurutan atau kategori.

php
<?php
$_GET['urutan'] = 'nama; DROP TABLE';
$urutanSah = ['nama', 'tanggal', 'judul'];

$urutan = $_GET['urutan'] ?? 'tanggal';
if (!in_array($urutan, $urutanSah, true)) {
    $urutan = 'tanggal';
}
echo 'Urutan yang dipakai: ' . $urutan . PHP_EOL;
text Keluaran
Urutan yang dipakai: tanggal

Keluaran menunjukkan bahwa masukan yang memuat perintah asing jatuh ke nilai bawaan tanggal, sehingga nilai mentahnya tidak pernah mencapai query maupun keluaran. Perbandingan in_array dengan argumen ketiga true menggunakan kesetaraan ketat, sehingga nilai yang hanya mirip dengan pilihan sah juga ditolak. Nilai bawaan yang aman dipilih sebagai tempat jatuh bagi setiap masukan yang tidak lolos.

Memvalidasi format dengan filter_var#

Untuk format umum, ekstensi filter menyediakan konstanta pemeriksaan yang siap pakai. filter_var dengan konstanta FILTER_VALIDATE_EMAIL mengembalikan alamat itu sendiri apabila bentuknya sah dan false apabila tidak, sedangkan FILTER_VALIDATE_INT mengembalikan bilangan bulat atau false. Pola kembalian semacam ini membuat pemeriksaan dan konversi tipe terjadi sekaligus.

php
<?php
var_dump(filter_var('[email protected]', FILTER_VALIDATE_EMAIL));
var_dump(filter_var('budi tidak-valid', FILTER_VALIDATE_EMAIL));
var_dump(filter_var('17', FILTER_VALIDATE_INT));
var_dump(filter_var('tujuh belas', FILTER_VALIDATE_INT));
var_dump(filter_var('2abc', FILTER_VALIDATE_INT));
text Keluaran
string(19) "[email protected]"
bool(false)
int(17)
bool(false)
bool(false)

Keluaran menunjukkan bahwa string '17' dari form menjadi bilangan bulat sungguhan setelah pemeriksaan, sedangkan teks yang tidak memenuhi format ditolak dengan false. Dengan begitu, kode setelahnya selalu bekerja pada tipe yang benar dan tidak perlu mengonversi ulang. Konstanta lain seperti FILTER_VALIDATE_URL dan FILTER_VALIDATE_IP mengikuti pola yang sama, dan daftar lengkapnya ada pada halaman Validate filters di manual PHP.

Penting dicatat bahwa pemeriksaan format ini memastikan bentuk yang sah, bukan isi yang benar. Alamat email yang sah secara bentuk tetap mungkin bukan milik pengirim, sehingga verifikasi kepemilikan seperti tautan konfirmasi tetap diperlukan pada keperluan yang sensitif.

Memeriksa karakter dengan ctype_digit#

Pemeriksaan tingkat karakter berguna ketika aturannya lebih sederhana daripada format penuh. ctype_digit mengembalikan true hanya apabila seluruh karakter string adalah angka, sehingga tanda desimal dan string kosong ikut ditolak. Untuk nomor halaman atau kuantitas, pemeriksaan ini lebih ketat daripada is_numeric yang masih menerima bentuk lain seperti 1e3.

php
<?php
var_dump(ctype_digit('42'));
var_dump(ctype_digit('42abc'));
var_dump(ctype_digit('4.2'));
var_dump(ctype_digit(''));

$halaman = '3';
if (ctype_digit($halaman) && (int) $halaman > 0) {
    echo 'Halaman sah: ' . $halaman . PHP_EOL;
} else {
    echo 'Halaman sah: 1' . PHP_EOL;
}
text Keluaran
bool(true)
bool(false)
bool(false)
bool(false)
Halaman sah: 3

Keluaran menegaskan bahwa dari empat bentuk masukan hanya satu yang lolos, sedangkan nomor halaman sah tetap berjalan dengan konversi (int) setelah pemeriksaan. Rangkaian ctype_digit dan pemeriksaan batas membentuk validasi yang ringkas tanpa ekspresi reguler, dan konversi (int) hanya dilakukan pada nilai yang sudah terbukti murni angka.

KebutuhanFungsiKembalian
Nilai tetapin_array dengan argumen ketiga truetrue atau false
Format emailfilter_var dengan FILTER_VALIDATE_EMAILstring atau false
Bilangan bulatfilter_var dengan FILTER_VALIDATE_INTint atau false
Angka murnictype_digittrue atau false

Tabel di atas merangkum pemilihan fungsi sesuai kebutuhan, dan seluruhnya mengikuti satu pola yang sama, yaitu memeriksa lebih dahulu sebelum nilai dipakai.

Kesalahan umum#

Empat kesalahan berikut paling sering muncul saat memvalidasi masukan.

  • Validasi hanya berada di browser. Permintaan yang dikirim langsung ke server melewati seluruh pemeriksaan browser, sehingga data tidak sah tetap sampai ke PHP. Perbaikannya adalah mengulang seluruh pemeriksaan di server sebelum data dipakai.
  • Penyaringan memakai blacklist kata terlarang. Daftar terlarang selalu tertinggal terhadap variasi baru dan mudah dilewati dengan pengodean yang berbeda. Perbaikannya adalah whitelist nilai yang sah beserta nilai bawaan yang aman.
  • Angka dipakai langsung dari $_GET tanpa pemeriksaan. Nilainya berupa string dan dapat berisi apa pun, sehingga query atau perhitungan menerima data rusak. Perbaikannya adalah FILTER_VALIDATE_INT atau ctype_digit sebelum konversi (int).
  • Alamat email diperiksa dengan ekspresi reguler buatan sendiri. Pola yang tidak lengkap menolak alamat yang sah atau menerima bentuk yang tidak wajar. Perbaikannya adalah FILTER_VALIDATE_EMAIL yang aturannya dijaga manual PHP.

Ringkasan#

  • Setiap data dari luar program dianggap tidak terpercaya, dan pemeriksaan yang menentukan berjalan di server.
  • Whitelist menetapkan nilai yang diizinkan lalu menolak sisanya, dan paling tepat untuk pilihan yang jumlahnya tetap.
  • filter_var memeriksa format umum sekaligus mengonversi tipe, sedangkan ctype_digit memeriksa angka murni pada tingkat karakter.
  • Masukan yang gagal validasi jatuh ke nilai bawaan yang aman, bukan dipakai dalam bentuk mentahnya.

Referensi#