ในตอนต้นของคู่มือ เราได้กล่าวไว้ว่าการกรองข้อมูลเป็นรากฐานสำคัญของการรักษาความปลอดภัยของแอปพลิเคชันเว็บในทุกภาษาและทุกแพลตฟอร์ม ซึ่งรวมถึงการตรวจสอบข้อมูลที่ป้อนเข้าและออกจากแอปพลิเคชัน และการออกแบบซอฟต์แวร์ที่ดีสามารถช่วยนักพัฒนาได้:
ตรวจสอบให้แน่ใจว่าการกรองข้อมูลไม่สามารถข้ามได้ ตรวจสอบ
ให้แน่ใจว่าข้อมูลที่ผิดกฎหมายไม่ส่งผลกระทบต่อข้อมูลทางกฎหมาย และ
ระบุแหล่งที่มาของข้อมูล
มีมุมมองต่างๆ มากมายเกี่ยวกับวิธีตรวจสอบให้แน่ใจว่าไม่สามารถข้ามการกรองข้อมูลได้ และสองมุมมองนั้นเป็นมุมมองที่กว้างกว่ามุมมองอื่นๆ และให้ความมั่นใจในระดับที่สูงกว่า
วิธีการจัดตารางเวลา วิธีนี้จะกำหนดเวลาด้วยสคริปต์ PHP เดียว (ผ่าน URL) การดำเนินการอื่นใดจะถูกรวมไว้โดยใช้การรวมหรือต้องการเมื่อจำเป็น โดยทั่วไปวิธีการนี้กำหนดให้แต่ละ URL ต้องส่งตัวแปร GET แยกต่างหากเพื่อจัดส่ง ตัวแปร GET นี้ถือเป็นการออกแบบที่เรียบง่ายกว่าซึ่งแทนที่ชื่อสคริปต์ ตัวอย่างเช่น:
http://example.org/dispatch.php?task=print_formdispatch.php เป็นไฟล์รูทเพียงไฟล์เดียว (รูทเอกสาร) ช่วยให้นักพัฒนาสามารถทำสองสิ่งที่สำคัญมาก:
ใช้การประมวลผลการรักษาความปลอดภัยทั่วโลกใน Dispatch.php ในตอนเริ่มต้น และตรวจสอบให้แน่ใจว่าการประมวลผลเหล่านี้ไม่สามารถข้ามได้
ง่ายต่อการระบุตำแหน่งที่จำเป็นต้องกรองข้อมูล โดยเฉพาะอย่างยิ่งสำหรับการดำเนินการโฟลว์ควบคุมที่มีจุดประสงค์พิเศษบางอย่าง
ดูตัวอย่างต่อไปนี้สำหรับการสนทนาเพิ่มเติมเกี่ยวกับสคริปต์ Dispatch.php:
<?php/* Global Security Handling*/switch ($_GET['task']){case 'print_form':include '/inc/presentation/form.inc '; break;case 'process_form':$form_valid = false;include '/inc/logic/process.inc';if ($form_valid){include '/inc/presentation/end.inc';}else{include '/ inc/ Presentation/form.inc';}break;default:include '/inc/presentation/index.inc';break;}?>หากนี่เป็นสคริปต์ PHP ที่สาธารณะเข้าถึงได้เพียงตัวเดียว คุณสามารถมั่นใจได้ว่าโปรแกรมนี้ได้รับการออกแบบ ช่วยให้มั่นใจว่าไม่สามารถข้ามการประมวลผลความปลอดภัยทั่วโลกเริ่มต้นได้ นอกจากนี้ยังช่วยให้นักพัฒนาเห็นขั้นตอนการควบคุมงานเฉพาะได้อย่างง่ายดายอีกด้วย ตัวอย่างเช่น มันง่ายที่จะรู้โดยไม่ต้องเรียกดูโค้ดทั้งหมด: เมื่อ $form_valid เป็นจริง end.inc จะเป็นโค้ดเดียวที่แสดงให้ผู้ใช้เห็น เนื่องจากเป็นโค้ดก่อนที่ process.inc จะรวมอยู่และเพิ่งถูกเตรียมใช้งานเป็นเท็จ สามารถระบุได้ว่าตรรกะภายในของ process.inc จะตั้งค่าเป็นจริง มิฉะนั้นแบบฟอร์มจะปรากฏขึ้นอีกครั้ง (อาจมีข้อความแสดงข้อผิดพลาดที่เกี่ยวข้อง)
โปรดทราบว่าหากคุณใช้ไฟล์คำสั่งไดเร็กทอรี เช่น index.php (แทนการจัดส่ง.php) คุณสามารถใช้ที่อยู่ URL ในลักษณะนี้: http://example.org/?task=print_form
คุณยังสามารถใช้การเปลี่ยนเส้นทาง ApacheForceType หรือ mod_rewrite เพื่อปรับที่อยู่ URL: http://example.org/app/print-form
อีกวิธีหนึ่งในการรวมวิธีการคือการใช้โมดูลเดียวที่รับผิดชอบในการจัดการความปลอดภัยทั้งหมด โมดูลนี้รวมอยู่ที่ด้านหน้า (หรือด้านหน้าสุด) ของสคริปต์ PHP สาธารณะทั้งหมด อ้างถึงสคริปต์ต่อไปนี้ security.inc
<?phpswitch ($_POST['form']){case 'login':$allowed = array();$allowed[] = 'form';$allowed[] = 'username' ; $allowed[] = 'password';$sent = array_keys($_POST);if ($allowed == $sent){include '/inc/logic/process.inc';}break;}?>ในกรณีนี้ แต่ละแบบฟอร์มที่ส่งมาจะถือว่ามีค่าการยืนยันที่ไม่ซ้ำกันของแบบฟอร์ม และ security.inc จะประมวลผลข้อมูลในแบบฟอร์มที่จำเป็นต้องกรองอย่างอิสระ แบบฟอร์ม HTML ที่ใช้ข้อกำหนดนี้มีดังนี้:
<form action="/receive.php" method="POST"><input type="hidden" name="form" value="login" /><p>ชื่อผู้ใช้ : <input type="text" name="username" /></p><p>รหัสผ่าน:<input type="password" name="password" /></p><input type="submit" / > </form>อาร์เรย์ที่เรียกว่า $allowed ใช้เพื่อตรวจสอบว่าตัวแปรฟอร์มใดที่ได้รับอนุญาต รายการนี้ควรจะสอดคล้องกันก่อนที่จะประมวลผลแบบฟอร์ม การควบคุมกระบวนการตัดสินใจว่าจะดำเนินการใด และ process.inc คือจุดที่ข้อมูลที่กรองจริงมาถึง
โปรดทราบว่าวิธีที่ดีกว่าเพื่อให้แน่ใจว่า security.inc จะถูกรวมไว้ที่จุดเริ่มต้นของทุกสคริปต์เสมอคือการใช้การตั้งค่า auto_prepend_file
ตัวอย่างการกรอง การสร้างไวท์ลิสต์มีความสำคัญมากสำหรับการกรองข้อมูล เนื่องจากเป็นไปไม่ได้ที่จะยกตัวอย่างข้อมูลทุกรูปแบบที่คุณอาจพบ ตัวอย่างบางส่วนจึงช่วยให้คุณเข้าใจโดยทั่วไปได้
รหัสต่อไปนี้ตรวจสอบที่อยู่อีเมล:
<?php$clean = array();$email_pattern = '/^[^@s<&>]+@([-a-z0-9]+.) +[ az]{2,}$/i';if (preg_match($email_pattern, $_POST['email'])){$clean['email'] = $_POST['email'];}?> ด้านล่างโค้ด ตรวจสอบให้แน่ใจว่าเนื้อหาของ $_POST['color'] เป็นสีแดง เขียว หรือน้ำเงิน:
<?php$clean = array();switch ($_POST['color']){case 'red':case 'green ' :case 'blue':$clean['color'] = $_POST['color'];break;}?>โค้ดต่อไปนี้ช่วยให้แน่ใจว่า $_POST['num'] เป็นจำนวนเต็ม:
<?php$ clean = array ();if ($_POST['num'] == strval(intval($_POST['num']))){$clean['num'] = $_POST['num'];} >ต่อไปนี้ รหัสทำให้มั่นใจได้ว่า $_POST['num'] เป็นแบบ float:
<?php$clean = array();if ($_POST['num'] == strval(floatval($_POST['num ']))){ $clean['num'] = $_POST['num'];}?> แต่ละตัวอย่างใช้อาร์เรย์ $clean ก่อนการแปลงชื่อ นี่เป็นแนวทางปฏิบัติที่ดีสำหรับนักพัฒนาในการพิจารณาว่าข้อมูลของตนอาจถูกบุกรุกหรือไม่ อย่าบันทึกข้อมูลใน $_POST หรือ $_GET หลังจากตรวจสอบความถูกต้องแล้ว ในฐานะนักพัฒนา คุณควรสงสัยข้อมูลที่บันทึกไว้ใน super global arrays เสมอ
ควรเสริมด้วยว่าการใช้ $clean สามารถช่วยคิดถึงสิ่งที่ยังไม่ถูกกรอง ซึ่งคล้ายกับบทบาทของรายการที่อนุญาตมากกว่า สามารถปรับปรุงระดับความปลอดภัยได้
หากคุณจัดเก็บข้อมูลที่ผ่านการตรวจสอบแล้วใน $clean เท่านั้น ความเสี่ยงเพียงอย่างเดียวในการตรวจสอบข้อมูลก็คือไม่มีองค์ประกอบอาร์เรย์ที่คุณกำลังอ้างอิงอยู่ ไม่ใช่ข้อมูลอันตรายที่ไม่มีการกรอง
ระยะเวลา เมื่อสคริปต์ PHP เริ่มดำเนินการ หมายความว่าคำขอ HTTP ทั้งหมดสิ้นสุดลงแล้ว ณ จุดนี้ ผู้ใช้ไม่มีโอกาสที่จะส่งข้อมูลไปยังสคริปต์ ดังนั้นจึงไม่สามารถป้อนข้อมูลลงในสคริปต์ได้ (แม้ว่าจะเปิด register_globals ก็ตาม) นี่คือเหตุผลว่าทำไมการเริ่มต้นตัวแปรจึงเป็นแนวทางปฏิบัติที่ดีมาก