Haruskah saya membersihkan alamat email sebelum meneruskannya ke fungsi is_email ()?

13

Saya menggunakan is_email()untuk memeriksa apakah alamat email yang diberikan pengguna valid. Sebagai contoh:

$email = $_POST['email'];
if ( is_email( $email ) )
    // Do something.

Sejauh pengetahuan saya, tidak ada dalam fungsi ini menulis info ke database. Haruskah saya membersihkan $emailsebelum saya meneruskannya ke fungsi?

Henryrywright
sumber
Kaiser, terima kasih untuk hasil editnya. Ini sebenarnya sanitasi untuk saya, tetapi saya yakin sebagian besar pembaca di sini akan menggunakan z :)
henrywright

Jawaban:

5

Melihat is_email()fungsionalitas pada trac, sepertinya Anda tidak perlu sanatizie karena hanya pengujian string. Saya bahkan akan mengatakan bahwa jika fungsi ini mengembalikan true, Anda tidak perlu membersihkannya sebelum mengirimnya ke database.

Howdy_McGee
sumber
Pikiranku persis tentang pengujian string. Saya pikir saya masih akan membersihkan sebelum mengirim ke db, Anda mungkin benar bahwa itu tidak perlu, tapi saya gugup ketika datang untuk hal-hal ini :)
henrywright
Benar, lebih baik aman daripada menyesal dan overhead sanitasi akan sepenuhnya tidak terlihat.
Howdy_McGee
18

Inti WordPress dan PHP

The is_email()Fungsi Sumber adalah implementasi WordPress khas dan tidak bekerja sepenuhnya dengan apa yang RFC 6531 memungkinkan. Salah satu alasannya mungkin, bahwa FILTER_VALIDATE_EMAILkonstanta PHP default untuk filter_var()tidak jauh lebih baik dalam memvalidasi sesuatu sesuai dengan pedoman The Internet Engineering Task Force (IETF®) .

Standar

Intinya adalah bahwa RFC 6531 memungkinkan "karakter Unicode di luar rentang ASCII" . Yaitu mereka adalah (untuk bagian lokal - sebelum @):

  • Huruf besar dan kecil Bahasa Inggris (a – z, A – Z) (ASCII: 65–90, 97–122)
  • Digit 0to 9(ASCII: 48–57)
  • Karakter khusus ini: ! # $ % & ' * + - / = ? ^ _ ` { | } ~
  • Karakter .(titik, titik, titik) (ASCII: 46) asalkan itu bukan karakter pertama atau terakhir, dan asalkan juga tidak muncul secara berurutan (mis. [email protected]Tidak diperbolehkan).
  • Karakter khusus diizinkan dengan batasan. Mereka:
    • Ruang dan "(),:;<>@[\](ASCII: 32, 34, 40, 41, 44, 58, 59, 60, 62, 64, 91-93)
    • Batasan untuk karakter khusus adalah bahwa karakter tersebut hanya boleh digunakan ketika terdapat di antara tanda kutip, dan bahwa 2 di antaranya (garis miring terbalik \ dan tanda kutip "(ASCII: 92, 34)) juga harus didahului dengan garis miring terbalik \(misalnya "\\"dan "\"") .
  • Komentar diperbolehkan dengan tanda kurung di kedua ujung bagian lokal; misalnya john.smith(comment)@example.comdan (comment)[email protected]keduanya sama dengan "[email protected]", tetapi john.(comment)[email protected]tidak valid.
  • Karakter internasional di atas U+007F, yang dikodekan sebagai UTF-8, diizinkan oleh RFC 6531, meskipun sistem surat mungkin membatasi karakter mana yang akan digunakan ketika menetapkan bagian lokal.

dan untuk bagian global / domain:

Bagian nama domain dari alamat email harus sesuai dengan panduan ketat: harus sesuai dengan persyaratan untuk nama host, yang terdiri dari huruf, angka, tanda hubung, dan titik. Selain itu, bagian domain dapat berupa alamat IP literal, dikelilingi oleh kurung kurawal, seperti jsmith@[192.168.2.1]atau jsmith@[IPv6:2001:db8::1][...]

Sumber: Wikipedia

Apa yang valid

Ini dapat menyebabkan alamat email yang aneh, tetapi valid seperti berikut ini:

  • [email protected]
  • (comment)[email protected]
  • "this is v@lid!"@example.com
  • "much.more unusual"@example.com
  • postbox@com
  • admin@mailserver1
  • "()<>[]:,;\\@\"\\\\!#$%&\'*+-/=?^_`{}| ~.a"@example.org
  • " "@example.org

Sumber: php.net / author [email protected] - contoh diperbaiki oleh penulis posting ini

Batas

Ada juga batas lokal & panjang domain:

Format alamat email adalah di local-part@domainmana bagian lokal mungkin panjangnya hingga 64 karakter dan nama domain mungkin memiliki maksimal 253 karakter - tetapi panjang maksimum 256 karakter dari jalur maju atau mundur membatasi seluruh alamat email untuk menjadi tidak lebih dari 254 karakter . [2] definisi formal dalam RFC 5322 (bagian 3.2.3 dan 3.4.1) dan RFC 5321 - dengan bentuk yang lebih mudah dibaca diberikan dalam RFC informasi 3696 [3] dan ralat terkait .

Sumber: Wikipedia

Pembatasan WordPress

Dan inilah yang diperiksa WordPress untuk:

  • Tes untuk panjang minimum email dapat: strlen( $email ) < 3
  • Tes untuk karakter @ setelah posisi pertama: strpos( $email, '@', 1 ) === false
  • Tes untuk karakter yang tidak valid: !preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local )
  • Tes untuk urutan periode: preg_match( '/\.{2,}/', $domain )
  • Tes untuk periode dan spasi putih terdepan dan akhir: trim( $domain, " \t\n\r\0\x0B." ) !== $domain
  • Asumsikan domain akan memiliki setidaknya dua subs: $subs = explode( '.', $domain );dan kemudian
    • 2 > count( $subs )
    • trim( $sub, " \t\n\r\0\x0B-" ) !== $sub
    • !preg_match('/^[a-z0-9-]+$/i', $sub )

Sumber: WP Core v4.0

Penyaring & validasi khusus

Semua kasus yang disebutkan di atas akan memicu is_email()untuk kembali palsu. Hasilnya adalah filter-mampu (panggilan balik dapat dilampirkan) dan filter akan memiliki tiga argumen, di mana argumen terakhir adalah alasannya. Contoh:

return apply_filters( 'is_email', false, $email, 'sub_hyphen_limits' );

yang berarti bahwa Anda dapat mengganti hasil yang dikembalikan oleh pemeriksaan khusus.

Ini memungkinkan Anda untuk menambahkan pemeriksaan khusus, misalnya untuk mengizinkan domain Umlaut, bagian domain khusus TLD, dll.

Kesimpulan

WordPress aman untuk sebagian besar kasus, tetapi lebih ketat karena server mail sebenarnya harus sesuai dengan RFC. Ingatlah bahwa tidak setiap server email akan sejajar dengan pedoman RF 6531.

Edit

Sidefact lucu: Ada dua fungsi terkait di dalamnya ~/wp-includes/formatting: is_email()dan sanitize_email(). Mereka praktis memiliki fungsi yang sama . Saya tidak tahu mengapa seseorang memutuskan bahwa itu akan menjadi ide yang baik untuk menyalin konten fungsi dari satu ke yang lain, bukan hanya menambahkan satu sebagai panggilan balik ke filter yang disediakan oleh yang lain. Karena sejak v0.71 dan karena v1.5 adalah sama, saya pribadi akan menggunakan nanti ketika Anda mendapatkan string yang dibersihkan. Perhatikan bahwa bahkan menyatakan bahwa itu tidak sesuai dengan RFC.is_email() sanitize_email() is_email()

kaisar
sumber
Jadi Anda mengatakan, secara teori, akan ada alamat email di luar sana yang benar-benar valid menurut RFC 6531 tetapi ini akan dianggap tidak valid oleh WordPress?
henrywright
Beberapa ya. Misalnya domain hanya TLD, domain umlaut, dll. Seperti yang dapat Anda baca di paragraf terakhir sebelum kesimpulan dalam jawaban. Silakan baca jawabannya lagi. Saya tahu banyak yang harus dibungkus, tapi itu sepadan.
kaiser
1
Saya sebenarnya sudah membacanya dua kali karena ini adalah sesuatu yang layak dipahami! Terima kasih atas jawaban terinci seperti itu :)
henrywright
2

Sanitasi semua hal!

Salah satu aturan utama keamanan adalah jangan pernah mempercayai input dari pengguna. Secara umum, saya tidak peduli dengan implementasi is_email () atau fungsi spesifik lainnya, atau jika fungsi itu melakukan sesuatu yang berbahaya dengan apa yang saya berikan. Mungkin implementasinya akan berubah suatu hari nanti. Siapa tahu. Saya harus berasumsi itu bisa dikompromikan. Asumsinya harus selalu bahwa input pengguna aktif bermusuhan, jadi dua kali lipat untuk apa pun yang akhirnya ditujukan untuk database, dan untuk membersihkan setiap bit input pengguna sebelum menyerahkannya ke beberapa fungsi. Ini bagus, kebersihan keamanan umum.

JesseM
sumber
Saya pikir Anda menekan kepala ketika Anda mengatakan Anda tidak pernah tahu apakah implementasinya akan berubah. Mungkin OK untuk tidak membersihkan sekarang, tetapi siapa yang tahu apakah itu akan berubah di kemudian hari?
henrywright