Sanitasi dan Validasi Data dengan WordPress
() translation by (you can also view the original English article)
Keamanan yang tepat sangat penting untuk menjaga situs Anda atau tema atau pengguna plug-in Anda aman. Bagian dari itu berarti validasi dan sanitasi data yang tepat. Pada artikel ini kita akan melihat mengapa ini penting, apa yang perlu dilakukan, dan fungsi WordPress apa yang bisa membantu.
Karena tampaknya ada beragam penafsiran tentang apa arti istilah 'validasi', 'escaping' dan 'sanitasi', pertama-tama saya akan menjelaskan apa yang saya maksud dengan mereka dalam artikel ini:
- Validasi – Ini adalah pemeriksaan yang dijalankan untuk memastikan data yang Anda miliki adalah sebagaimana mestinya. Misalnya, bahwa e-mail terlihat seperti alamat e-mail, bahwa tanggal adalah tanggal dan nomor (atau digunakan sebagai nomor) adalah sebuah bilangan bulat
- Sanitasi / Escaping – Ini adalah filter yang diterapkan pada data agar membuatnya 'aman' dalam konteks tertentu. Misalnya, untuk menampilkan kode HTML di area teks, akan diperlukan untuk mengganti semua tag HTML dengan entitas mereka yang setara
Mengapa Sanitasi Penting?
Bila data disertakan dalam beberapa konteks (misalnya dalam dokumen HTML) – data tersebut dapat disalahartikan sebagai kode untuk lingkungan itu (misalnya kode HTML). Jika data tersebut mengandung kode berbahaya, maka dengan menggunakan data tersebut tanpa melakukan sanitasi, berarti kode tersebut akan dieksekusi. Kode tersebut bahkan tidak harus berbahaya untuk menimbulkan efek yang tidak diinginkan. Tugas sanitasi adalah memastikan bahwa kode apa pun dalam data tidak ditafsirkan sebagai kode – jika tidak, Anda mungkin akan berakhir seperti sekolah Bobby Tables...
Contoh yang tampaknya tidak berbahaya mungkin pra-mengisi kolom pencarian dengan istilah yang saat ini ditanyakan, menggunakan $_GET['s']
yang tidak ter-escape:
1 |
|
2 |
<form method="get" id="searchform" action="<?php echo esc_url( home_url( '/' ) ); ?>"> |
3 |
<input type="text" class="field" name="s" id="s" value="<?php echo $_GET['s']; ?>"/> |
4 |
<input type="submit" class="submit" name="submit" id="searchsubmit" value="Search" /> |
5 |
</form>
|
Ini membuka kerentanan yang memungkinkan javascript disuntikkan, misalnya, menipu seseorang untuk mengunjungi http://yoursite.com?s"/><script>alert('Injected javascript')</script>
. Istilah pencariannya 'melompat' dari atribut nilai, dan bagian data yang mengikutinya ditafsirkan sebagai kode dan dieksekusi. Untuk mencegah hal ini, WordPress menyediakan get_search_query
yang mengembalikan kueri pencarian yang telah dibersihkan. Meskipun ini adalah contoh yang 'tidak berbahaya', skrip yang disuntikkan bisa jadi jauh lebih jahat dan paling baik hanya akan 'merusak' form jika istilah pencarian berisi tanda kutip ganda.
Bagaimana kode berbahaya (atau sebaliknya) ini mungkin telah menemukan jalannya ke situs Anda bukan masalah di sini – melainkan untuk mencegahnya dijalankan. Kita juga tidak membuat asumsi tentang sifat kode yang tidak diinginkan ini, atau maksudnya – itu bisa saja merupakan kesalahan pada bagian pengguna. Ini membawa saya ke aturan No.1...
Aturan No. 1: Jangan Percaya Siapapun
Ini adalah pepatah umum yang digunakan berkaitan dengan sanitasi data, dan ini sesuatu yang baik. Idenya adalah bahwa Anda tidak boleh berasumsi bahwa setiap data yang dimasukkan oleh pengguna adalah aman. Anda juga harus tidak menganggap bahwa data yang Anda dapatkan dari database adalah aman – bahkan jika Anda membuatnya 'aman' sebelum memasukkannya ke sana. Padahal, apakah data bisa dianggap 'aman' tidak masuk akal tanpa konteks. Terkadang data yang sama dapat digunakan dalam beberapa konteks pada halaman yang sama. Judul misalnya, dapat berisi tanda petik atau tanda petik ganda dengan aman saat berada di dalam tag header – namun akan menimbulkan masalah jika digunakan (tak ter-escape) di dalam atribut title dari tag link. Jadi agak sia-sia membuat data 'aman' saat menambahkannya ke database, karena seringkali tidak mungkin membuat data aman untuk semua konteks secara bersamaan. (Tentu saja perlu dibuat aman untuk ditambahkan ke database – tapi kita akan membahasnya nanti).
Bahkan jika Anda hanya bermaksud menggunakan data tersebut dalam satu konteks tertentu, katakanlah sebuah form, masih sia-sia untuk membersihkan data saat menulis ke database karena, sesuai Aturan No. 1, Anda tidak dapat mempercayai bahwa itu masih aman saat Anda mengeluarkannya lagi.
Aturan No. 2: Validasi pada Input, Escape saat Output
Ini adalah pepatah prosedural yang menentukan kapan Anda harus memvalidasi data, dan kapan Anda membersihkannya. Sederhananya – validasi data Anda (periksa apa adanya – dan itu 'valid') segera setelah Anda menerimanya dari pengguna. Bila Anda datang untuk menggunakan data ini, misalnya saat Anda mengeluarkannya, Anda perlu meng-escape (atau membersihkannya). Apa bentuk sanitasi ini, tergantung sepenuhnya pada konteks yang Anda gunakan di dalamnya.
Saran terbaik adalah melakukan 'terlambat' ini: escape data Anda segera sebelum Anda menggunakan atau menampilkannya. Dengan cara ini Anda dapat yakin bahwa data Anda telah dibersihkan dengan benar dan Anda tidak perlu mengingat apakah data telah diperiksa sebelumnya.
Aturan No. 3: Mempercayai WordPress
Anda mungkin berpikir "Ok, validasikan sebelum menulis ke database dan membersihkan saat menggunakannya. Tapi bukankah saya perlu memastikan data aman untuk ditulis ke database?". Secara umum, ya. Saat menambahkan data ke database, atau hanya menggunakan masukan untuk berinteraksi dengan database, Anda harus meng-escape data jikalau di dalamnya berisi perintah SQL. Tapi ini membawa saya ke Aturan No. 3, yang berhadapan Aturan No. 1: Mempercayai WordPress
Pada artikel sebelumnya, saya mengambil masukan pengguna (dikirim dari form pencarian melalui AJAX) dan menggunakannya langsung dengan get_posts()
untuk mengembalikan postingan yang sesuai dengan kueri pencarian:
1 |
|
2 |
$posts = get_posts( array( |
3 |
's'=>$_REQUEST['term'] |
4 |
) ); |
Seorang pembaca yang jeli melihat bahwa saya tidak melakukan sanitasi apapun – dan mereka benar. Tapi saya tidak perlu melakukannya. Bila Anda menggunakan fungsi tingkat tinggi seperti get_posts()
, Anda tidak perlu khawatir tentang membersihkan data – karena kueri database semuanya ter-escape dengan banar oleh internal WordPress. Ini adalah masalah yang berbeda sama sekali jika Anda menggunakan kueri SQL langsung – tapi kita akan melihatnya di bagian selanjutnya. Demikian pula, fungsi seperti the_title()
, the_permalink()
, the_content()
dll melakukan sanitasi mereka sendiri (untuk konteks yang sesuai).
Validasi Data
Bila Anda menerima data yang dimasukkan oleh pengguna, penting untuk memvalidasinya. (API pengaturan, yang dibahas dalam seri ini, memungkinkan Anda menentukan fungsi callback untuk melakukan hal ini). Data tidak valid dapat dikoreksi dengan otomatis, atau prosesnya dibatalkan dan pengguna dikembalikan ke form untuk mencoba lagi (mudah-mudahan dengan pesan kesalahan yang sesuai). Perhatian di sini bukanlah keamanan tapi lebih ke validitas – jika Anda melakukannya dengan benar, WordPress akan segera menambahkan data ke database dengan aman. Apa artinya 'valid' terserah Anda – itu bisa berarti alamat email yang valid, bilangan bulat positif, teks dengan panjang terbatas, atau salah satu dari array opsi yang ditentukan. Bagaimanapun Anda bertujuan untuk menentukan validitasnya, WordPress menawarkan banyak fungsi yang bisa membantu.
Nomor
Ketika mengharapkan data numerik, dimungkinkan untuk memeriksa apakah data 'adalah beberapa bentuk nomor', misalnya is_int
atau is_float
. Biasanya, ini cukup hanya memasukkan data sebagai angka dengan: intval
atau floatval
.
Jika Anda perlu memastikan nomornya ditambahkan dengan angka nol didepannya, WordPress memberikan fungsi zeroise()
. Yang mengambil parameter berikut:
- Number – nomor untuk tambahan
- Threshold – jumlah digit nomor yang akan ditambahkan
Sebagai contoh:
1 |
|
2 |
echo zeroise(70,4); // Prints 0070 |
Untuk memerikasi validitas e-mail, WordPress memiliki fungsi is_email()
. Fungsi ini menggunakan pemeriksaan sederhana untuk memvalidasi alamat. Misalnya, ia memeriksa bahwa itu berisi simbol '@', lebih panjang dari 3 karakter, domain hanya berisi alfanumerik dan tanda hubung, dan sebagainya. Jelas, tidak memeriksa apakah alamat e-mail benar-benar ada. Dengan asumsi alamat e-mail lulus pemeriksaan, itu dikembalikan, jika tidak 'false' dikembalikan.
1 |
|
2 |
$email = is_email('someone@e^ample.com'); |
3 |
// $email is set to false.
|
4 |
|
5 |
$email = is_email('someone@example.com'); |
6 |
// $email is set to 'someone@example.com'.
|
HTML
Seringkali Anda mungkin ingin mengizinkan hanya beberapa tag HTML di data Anda – misalnya dalam komentar yang diposkan di situs Anda. WordPress menyediakan sekeluarga dari fungsi form wp_kses_*
(KSES Strips Evil Scripts). Fungsi ini menghapus (beberapa subset dari) tag HTML, dan dapat digunakan untuk memastikan bahwa tautan dalam data merupakan protokol yang ditentukan. Misalnya fungsi wp_kses()
menerima tiga argumen:
-
content
– (string) Konten untuk disaring melalui kses -
allowed_html
– Array di mana setiap kunci adalah elemen HTML yang diizinkan dan nilainya adalah array atribut yang diizinkan untuk elemen tersebut -
allowed_protocols
– Opsional. Protokol yang diizinkan di tautan (misalnyahttp
,mailto
,feed
dll)
wp_kses()
adalah fungsi yang sangat fleksibel, memungkinkan Anda menghapus tag yang tidak diinginkan, atau hanya atribut yang tidak diinginkan dari tag. Misalnya, hanya mengizinkan tag <strong>
atau <a>
(namun hanya mengizinkan atribut href):
1 |
|
2 |
$content = "<em>Click</em> <a title='click for wp.tuts+' href='http://wp.tutsplus.com'>here</a> to visit <strong> wptuts+ </strong>"; |
3 |
|
4 |
echo wp_kses( $content, array( |
5 |
'strong' => array(), |
6 |
'a' => array('href') |
7 |
) ); |
8 |
|
9 |
// Prints the HTML "Click <a href='http://wp.tutsplus.com'>here</a> to visit <strong> wptuts+ </strong>":
|
10 |
Click <a href="http://wp.tutsplus.com">here</a> to visit <strong> wptuts+ </strong> |
Tentu saja, menentukan setiap tag yang diizinkan dan setiap atribut yang diijinkan bisa menjadi tugas yang sulit. Juga, WordPress menyediakan fungsi lain yang memungkinkan Anda menggunakan wp_kses
dengan tag dan protokol yang telah ditentukan sebelumnya – yaitu yang digunakan untuk memvalidasi postingan dan komentar:
Fungsi di atas sangat membantu dalam memastikan bahwa HTML yang diterima dari pengguna hanya berisi elemen dalam daftar putih. Setelah kita selesai melakukannya, kita juga ingin memastikan bahwa setiap tag seimbang, yaitu setiap tag pembuka memiliki tag penutup yang sesuai. Untuk ini kita bisa menggunakan balanceTags()
. Fungsi ini menerima dua argumen:
- content – Konten untuk memfilter dan menyeimbangkan tag
- force balance – True atau false, apakah akan memaksa penyeimbangan tag
1 |
|
2 |
// Content with missing closing </strong> tag
|
3 |
$content = "<em>Click</em> <a href='http://wp.tutsplus.com'>here</a> to visit <strong> wptuts+"; |
4 |
|
5 |
echo balanceTags($content,true), |
6 |
|
7 |
// Prints the HTML "Click <a href='http://wp.tutsplus.com'>here</a> to visit <strong> wptuts+ </strong>"
|
Nama file
Jika Anda ingin membuat file di salah satu direktori situs web Anda, Anda ingin memastikan bahwa nama file valid dan legal. Anda juga ingin memastikan bahwa nama file itu unik untuk direktori itu. Untuk ini WordPress menyediakan:
-
sanitize_file_name( $filename )
– sanitasi (atau memvalidasi) nama file dengan menghapus karakter yang ilegal dalam nama file pada sistem operasi tertentu atau yang memerlukan perintah escape pada command line. Mengganti spasi dengan tanda hubung dan garis hubung berturut-turut dengan tanda hubung tunggal dan menghapus titik, garis hubung dan garis bawah dari awal dan akhir dari nama file. -
wp_unique_filename( $dir, $filename )
– mengembalikan nama file yang dibersihkan yang unik (untuk direktori$dir
), (menggunakansanitize_file_name
).
Data dari Field Teks
Saat menerima data yang dimasukkan ke dalam field teks, Anda mungkin ingin menghapus spasi ekstra, tab dan jeda baris, serta menghapus tag apapun. Untuk ini WordPress menyediakan sanitize_text_field()
.
Tombol
WordPress juga menyediakan sanitize_key
. Ini adalah fungsi yang sangat generik (dan kadang berguna). Hanya memastikan variabel yang dikembalikan hanya berisi huruf kecil alfanumerik, tanda hubung, dan garis bawah.
Sanitasi Data
Sedangkan validasi berkaitan dengan memastikan data valid – sanitasi data adalah tentang membuatnya aman. Sementara beberapa fungsi validasi yang disebut di atas mungkin berguna dalam memastikan data aman – secara umum, ini tidaklah cukup. Bahkan data 'valid' mungkin tidak aman dalam konteks tertentu.
Aturan No. 4: Membuat Data Aman Adalah Tentang Konteks
Sederhananya Anda tidak bisa bertanya "Bagaimana cara membuat data ini aman?". Sebagai gantinya Anda harus bertanya, "Bagaimana cara membuat data ini aman untuk digunakan di X".
Untuk menggambarkan hal ini, misalkan Anda memiliki widget dengan textarea di mana Anda ingin mengizinkan pengguna memasukkan beberapa HTML. Misalkan mereka kemudian memasukkan:
1 |
|
2 |
<textarea name="my-textarea"></textarea> Hello World |
Ini sangat valid, dan aman, HTML – namun saat Anda mengklik save, kita menemukan bahwa teks tersebut telah melompat keluar dari textarea. Kode HTML tidak aman sebagai nilai untuk textarea:



Apa yang aman digunakan dalam satu konteks, tidak harus aman di tempat lain. Kapanpun Anda menggunakan atau menampilkan data, Anda harus mengingat bentuk sanitasi apa yang perlu dilakukan untuk memanfaatkan data tersebut dengan aman. Inilah sebabnya mengapa WordPress sering menyediakan beberapa fungsi untuk konten yang sama, misalnya:
-
the_title
– untuk menggunakan judul dalam HTML standar (di dalam tag header, misalnya) -
the_title_attribute
– untuk menggunakan judul sebagai nilai atribut (biasanya atribut judul pada tag<a>
) -
the_title_rss
– untuk menggunakan judul di RSS feed
Semua ini melakukan sanitasi yang diperlukan untuk konteks tertentu – dan jika Anda menggunakannya, pastikan Anda harus menggunakan yang benar. Terkadang, kita perlu melakukan sanitasi kita sendiri – seringkali karena kita memiliki masukan kustom di luar judul posting standar, permalink, konten dll yang ditangani WordPress untuk kita.
Meng-escape HTML
Saat mencetak variabel ke halaman kita perlu memperhatikan bagaimana browser akan menafsirkannya. Mari pertimbangkan contoh berikut:
1 |
|
2 |
<h1> <?php echo $title; ?> </h1> |
Misalnya $title = <script>alert (script 'Injected javascript')</script>
. Daripada menampilkan tag <script>
HTML, mereka akan diartikan sebagai HTML dan javascript terlampir akan disuntikkan ke dalam halaman.
Bentuk injeksi ini (seperti juga ditunjukkan dalam contoh form pencarian) disebut Cross-site scripting dan contoh jinak ini memungkiri keparahannya. Skrip yang disuntikkan pada dasarnya dapat mengendalikan browser dan 'bertindak atas nama' pengguna atau mencuri cookies pengguna. Ini menjadi masalah yang lebih serius lagi jika pengguna sudah login. Untuk mencegah agar variabel tercetak di dalam HTML ditafsirkan sebagai HTML, WordPress menyediakan fungsi esc_html
yang terkenal. Dalam contoh ini:
1 |
|
2 |
<h1> <?php echo esc_html($title); ?> </h1> |
Meng-escape Atribut
Sekarang perhatikan contoh berikut ini:
1 |
|
2 |
<?php $value = 'my-value" onfocus="alert(\"Injected javascript\")"'; ?> |
3 |
<input type="text" name="myInput" value="<?php echo $value;?>"/> |
Karena $value
berisi tanda kutip ganda, tidak ter-escape itu bisa melompat keluar dari atribut nilai dan menyuntikkan skrip, misalnya dengan menggunakan atribut onfocus
. Untuk meng-escape karakter yang tidak aman (seperti tanda petik, dan tanda petik ganda dalam kasus ini), WordPress menyediakan fungsi esc_attr
. Seperti esc_html
, ia menggantikan karakter 'tidak aman' menurut entitas mereka yang setara. Sebenarnya, pada saat penulisan, fungsi ini identik – namun Anda tetap harus menggunakan yang sesuai untuk konteksnya.
Untuk contoh ini kita harus memiliki:
1 |
|
2 |
<?php $value = 'my-value" onfocus="alert(\"Injected javascript\")"'; ?> |
3 |
<input type="text" name="myInput" value="<?php echo esc_attr($value);?>"/> |
Baik esc_html
dan esc_attr
juga hadir dengan varian __
, _e
, dan _x
.
-
esc_html__('Text to translate', 'plugin-domain')
/esc_attr__
– mengembalikan teks terjemahan yang di-escape, -
esc_html_e('Text to translate', 'plugin-domain')
/esc_attr_e
– menampilkan teks terjemahan yang di-escape dan akhirnya -
esc_html_x('Text to translate', $context, 'plugin-domain')
/esc_attr_x
– menerjemahkan teks sesuai dengan konteks yang dilewatkan, dan kemudian mengembalikan terjemahan yang di-escape
Nama Kelas HTML
Untuk nama kelas, WordPress menyediakan sanitize_html_class
– ini meng-escape variabel untuk digunakan dalam nama kelas, cukup dengan membatasi nilai yang dikembalikan ke alfanumerik, tanda hubung dan garis bawah. Catatan: Tidak memastikan nama kelasnya valid (referensi: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier).
Dalam CSS, pengenal hanya dapat berisi karakter
[a-zA-Z0-9]
dan ISO 10646 karakter U+00A0 dan yang lebih tinggi, ditambah tanda hubung (-
) dan garis bawah (_
); mereka tidak bisa dimulai dengan sebuah digit, dua tanda hubung, atau tanda hubung diikuti oleh satu digit. Pengenal juga dapat berisi karakter yang ter-escape dan karakter ISO 10646 sebagai kode numerik.
Meng-escape URL
Sekarang mari kita lihat praktik umum lainnya, mencetak variabel ke atribut href
:
1 |
|
2 |
<a href="<?php echo $url;?>" title="Link Title"> Link Text </a> |
Jelas rentan terhadap bentuk serangan yang sama seperti yang digambarkan dalam meng-escape HTML dan atribut. Tapi bagaimana jika $url
itu ditetapkan sebagai berikut:
1 |
|
2 |
$url = 'javascript:alert(\'Injected javascript\')' |
Saat mengklik link tersebut, fungsi alert akan dijalankan. Ini tidak berisi HTML, atau tanda petik yang memungkinkannya keluar dari atribut href – jadi esc_attr
tidak cukup di sini. Inilah sebabnya mengapa konteks itu penting: esc_attr($url)
akan aman dalam atribut title
, tapi tidak untuk atribut href
– dan ini karena protokol javascript – yang sangat valid – tidak boleh dianggap aman dalam konteks ini. Sebagai gantinya Anda harus menggunakan:
-
esc_url
– untuk meng-escape URL yang akan dicetak ke halaman. -
esc_url_raw
– untuk meng-escape URL yang ingin disimpan ke database atau digunakan dalam pengalihan URL.
esc_url
menghapus berbagai karakter yang berbahaya, dan mengganti tanda petik dan ampersand dengan entitas mereka setara. Kemudian memeriksa bahwa protokol yang digunakan diperbolehkan (javascript, secara default, tidak).
Apa yang esc_url_raw
lakukan hampir sama dengan esc_url
, tapi tidak menggantikan ampersand dan tanda kutip tunggal (yang tidak Anda inginkan, saat menggunakan URL sebagai URL, bukan menampilkannya).
Dalam contoh ini, kita menampilkan URL, jadi kita menggunakan esc_url
:
1 |
|
2 |
<a href="<?php echo esc_url($url);?>" title="Link Title"> Link Text </a> |
Meskipun tidak diperlukan dalam banyak kasus, kedua fungsi tersebut menerima array opsional untuk menentukan protokol mana (seperti http
, https
, ftp
, ftps
, mailto
, dll) yang ingin Anda izinkan.
Meng-escape JavaScript
Terkadang Anda ingin mencetak variabel javascript ke halaman (biasanya di head):
1 |
|
2 |
<script>
|
3 |
var myVar = '<?php echo $variable; ?>'; |
4 |
</script>
|
Sebenarnya, jika Anda melakukan ini, Anda hampir pasti akan menggunakan wp_localize_script()
– yang menangani sanitasi untuk Anda. (Jika ada yang bisa memikirkan alasan mengapa Anda perlu menggunakan metode di atas sebagai gantinya, saya ingin mendengarnya).
Namun, untuk membuat contoh di atas aman, Anda bisa menggunakan fungsi esc_js
:
1 |
|
2 |
<script>
|
3 |
var myVar = '<?php echo esc_js($variable); ?>'; |
4 |
</script>
|
Meng-escape Textarea
Saat menampilkan konten dalam textarea, esc_html
tidaklah cukup karena tidak mengkode ganda entitas. Sebagai contoh:
1 |
|
2 |
<?php $var = '<strong>text</strong> <b>bold</b>' ?> |
3 |
<textarea><?php echo esc_html($var); ?> </textarea> |
$var
yang tercetak di textarea akan muncul sebagai:
1 |
|
2 |
<strong>text</strong> <b>bold</b> |
Daripada juga mengkodekan &
sebagai &
di tag <b>
.
Untuk ini WordPress menyediakan esc_textarea
, yang hampir identik dengan esc_html
, namun mengkode ganda entitas. Intinya sedikit lebih dari pembungkus untuk htmlspecialchars
. Dalam contoh ini:
1 |
|
2 |
<?php $var = '<strong>text</strong> <b>bold</b>' ?> |
3 |
<textarea><?php echo esc_textarea($var); ?> </textarea> |
Antispambot
Menampilkan alamat e-mail di situs Anda membuat mereka rentan terhadap pemanen e-mail. Salah satu metode sederhana adalah dengan menyamarkan alamat e-mail. WordPress menyediakan antispambot
, yang mengkodekan bagian acak dari alamat e-mail ke entitas HTML mereka (dan heksadesimal yang setara jika $mailto = 1
). Pada setiap halaman memuat pengkodean harus berbeda dan sementara alamat yang dikembalikan tampil dengan benar di browser, maka seharusnya muncul sebagai gobbledygook ke spambots. Fungsi ini menerima dua argumen:
-
e-mail
– alamat untuk dikaburkan -
mailto
– 1 atau 0 (1 jika menggunakan protokol mailto di tag tautan)
1 |
|
2 |
$email = "joebloggs@example.com"; |
3 |
$email = sanitize_email($email); |
4 |
echo '<a href="mailto:'.antispambot($email,1).'" title="Click to e-mail me" >'.antispambot($email).' </a>'; |
String Kueri
Jika Anda ingin menambahkan (atau menghapus) variabel dari string kueri (ini sangat berguna jika Anda ingin mengizinkan pengguna memilih urutan posting Anda), cara teraman dan termudah adalah dengan menggunakan add_query_arg
dan remove_query_arg
. Fungsi-fungsi ini menangani semua escape yang diperlukan untuk argumen dan nilai mereka untuk digunakan di URL.
add_query_arg
menerima dua argumen:
-
query parameters
– array asosiatif dari parameter -> nilai -
url
– URL untuk menambahkan parameter dan nilainya. Jika dihilangkan, URL halaman saat ini digunakan
remove_query_arg
juga menerima dua argumen, yang pertama adalah array parameter untuk dihapus, yang kedua adalah seperti di atas.
1 |
|
2 |
// If we are at www.example.com/wp-admin/edit.php?post_type=book
|
3 |
$query_params = array ('page' => 'my-bage'); |
4 |
$url = add_query_arg( $query_params ); |
5 |
|
6 |
// Would set $url to be:
|
7 |
// www.example.com/wp-admin/edit.php?post_type=book&page=my-page
|
Validasi & Sanitasi
Seperti yang telah disebutkan sebelumnya, sanitasi tidak masuk akal tanpa konteks – jadi cukup sia-sia untuk membersihkan data saat menulis ke database. Seringkali, Anda perlu menyimpan data dengan format aslinya, dan bagaimanapun juga – Aturan No. 1 mengharuskan kita untuk selalu melakukan pembersihan terhadap output.
Validasi data, di sisi lain, harus dilakukan segera setelah diterima dan sebelum ditulis ke database. Idenya adalah bahwa data 'tidak valid' harus dikoreksi secara otomatis, atau ditandai ke data, dan hanya data yang valid yang harus diberikan ke database.
Yang mengatakan – Anda mungkin juga ingin melakukan validasi saat data ditampilkan juga. Padahal terkadang, 'validasi' juga akan memastikan bahwa data aman. Tapi prioritas di sini adalah pada keamanan dan Anda harus menghindari validasi berlebihan yang akan berjalan pada setiap pemuatan halaman (fungsi wp_kses_*
, misalnya, sangat mahal untuk dilakukan).
Meng-escape Database
Saat menggunakan fungsi seperti get_posts
atau kelas seperti WP_Query
dan WP_User_Query
, WordPress menangani sanitasi yang diperlukan dalam query database. Namun, ketika mengambil data dari tabel kustom, atau melakukan query SQL langsung pada database – sanitasi yang tepat kemudian terserah pada Anda. WordPress, bagaimanapun, menyediakan kelas yang sangat membantu, kelas $wpdb
, yang membantu meng-escape kueri SQL.
Mari kita pertimbangkan perintah 'SELECT
' dasar ini, di mana $age
dan $firstname
adalah variabel yang menyimpan usia dan nama yang kita kuerikan:
1 |
|
2 |
SELECT * WHERE age='$age' AND firstname = '$firstname' |
Kita belum meng-escape dari variabel-variabel ini, jadi kemungkinan perintah selanjutnya bisa disuntikkan. Contoh xkcd yang dipinjam dari atas:
1 |
|
2 |
$age = 14; |
3 |
$firstname = "Robert'; DROP TABLE Students;"; |
4 |
$sql = "SELECT * WHERE age='$age' AND firstname = '$firstname';"; |
5 |
$results = $wpdb->query |
Akan dijalankan sebagai perintah:
1 |
|
2 |
SELECT * WHERE age='14' AND firstname = 'Robert'; DROP TABLE Students;'; |
Dan menghapus seluruh tabel Students kita.
Untuk mencegah hal ini, kita bisa menggunakan metode $wpdb->prepare
. Ini menerima dua parameter:
- Perintah SQL sebagai string, di mana variabel string digantikan oleh pengganti
%s
dan angka desimal digantikan oleh pengganti%d
dan float oleh%f
- Array nilai untuk pengganti di atas, sesuai urutannya dalam kueri
Dalam contoh ini:
1 |
|
2 |
$age = 14; |
3 |
$firstname = "Robert'; DROP TABLE Students;"; |
4 |
$sql = $wpdb->prepare('SELECT * WHERE age=%d AND firstname = %s;',array($age,$firstname)); |
5 |
$results = $wpdb->get_results($sql); |
Query SQL yang ter-escape ($sql
dalam contoh ini) kemudian dapat digunakan dengan salah satu metode:
$wpdb->get_row($sql)
$wpdb->get_var($sql)
$wpdb->get_results($sql)
$wpdb->get_col($sql)
$wpdb->query($sql)
Memasukkan dan Memperbarui Data
Untuk memasukkan atau memperbarui data, WordPress membuat hidup lebih mudah dengan menyediakan metode $wpdb->insert()
dan $wpdb->update()
.
Metode $wpdb->insert()
menerima tiga argumen:
- Table name – nama dari tabel
- Data – array data untuk dimasukkan sebagai pasangan kolom->nilai
- Format – macam format untuk nilai yang sesuai ('
%s
', '%d
' atau '%f
')
1 |
|
2 |
$age = 14; |
3 |
$firstname = "Robert'; DROP TABLE Students;"; |
4 |
$wpdb->insert( |
5 |
'Students', |
6 |
array( 'firstname' => $firstname, 'age' => $age ), |
7 |
array( '%s', '%d' ) |
8 |
);
|
Metode $wpdb->update()
menerima lima argumen:
- Table name – nama dari tabel
- Data – array data untuk diperbarui sebagai pasangan kolom->nilai
- Where – susunan data yang cocok sebagai pasangan kolom->nilai
- Data Format – macam format untuk nilai data yang sesuai
- Where Format – macam format untuk nilai 'where' yang sesuai
1 |
|
2 |
// Update Robert'; DROP TABLE Students; to Bobby
|
3 |
|
4 |
$oldname = "Robert'; DROP TABLE Students;"; |
5 |
$newname = "Bobby"; |
6 |
$wpdb->update( |
7 |
'Students', |
8 |
array( 'firstname' => $newname ), |
9 |
array( 'firstname' => $oldname ), |
10 |
array( '%s' ), |
11 |
array( '%s' ) |
12 |
);
|
Baik metode $wpdb->insert()
dan $wpdb->update()
melakukan semua sanitasi yang diperlukan untuk menulis ke database.
Pernyataan Like
Karena metode $wpdb->prepare
menggunakan %
untuk membedakan pengganti, perhatian harus diambil saat menggunakan wildcard %
dalam pernyataan SQL LIKE. Codex menyarankan untuk meng-escape-nya dengan %
kedua. Atau Anda bisa meng-escape istilah yang akan dicari dengan like_escape
dan kemudian tambahkan wildcard %
jika sesuai, sebelum memasukkannya ke dalam kueri menggunakan metode prepare. Sebagai contoh:
1 |
|
2 |
$age=14; |
3 |
$firstname = "Robert'; DROP TABLE Students;"; |
4 |
SELECT * WHERE age=$age (firstname LIKE '%$firstname%'); |
Akan dibuat aman dengan:
1 |
|
2 |
$age=14; |
3 |
$firstname = "Robert'; DROP TABLE Students;"; |
4 |
SELECT * WHERE age=$age AND (firstname LIKE '%$firstname%'); |
5 |
$query = $wpdb->prepare('SELECT * WHERE age=%d AND (firstname LIKE %s);', array($age, '%'.like_escape($firstname).'%') ); |
Ringkasan
Ini bukanlah daftar lengkap fungsi yang tersedia untuk validasi dan sanitasi, namun seharusnya mencakup sebagian besar kasus penggunaan. Banyak fungsi-fungsi ini (dan lainnya) dapat ditemukan di /wp-includes/formatting.php
dan saya sangat menyarankan untuk menggali kode inti dan melihat bagaimana inti WordPress melakukan validasi dan sanitasi data.
Apakah artikel ini bermanfaat? Apakah Anda memiliki saran lebih lanjut tentang praktik terbaik untuk validasi data dan sanitasi di WordPress? Beri tahu kami di komentar di bawah ini.