PHP Form Validation

Trong bài này và các phần tiếp theo sẽ trình bày cách sử dụng PHP để xác thực các dữ liệu biểu mẫu

Xác thực biểu mẫu PHP


Hãy nghĩ đến sự AN TOÀN khi xử lý các biểu mẫu PHP!

Các ví dụ này sẽ chỉ ra cách xử lý các biểu mẫu PHP có lưu ý đến tính bảo mật. Việc xác nhận đúng cách dữ liệu biểu mẫu là điều quan trọng để bảo vệ biểu mẫu của bạn khỏi tin tặc và những kẻ gửi thư rác!

Biểu mẫu HTML mà chúng ta sẽ làm việc trong các chương này, chứa các trường input khác nhau: trường văn bản bắt buộc và tùy chọn, nút radio và nút submit:

Các quy tắc xác thực cho biểu mẫu trên như sau

Field Quy tắc xác thực
Name required, yêu cầu bắt buột, bao gồm ký tự và khoảng trắng
E-mail required, yêu cầu bắt buột, địa chỉ email đúng định dạng (chứa @ và .)
Website optional, yêu cầu không bắt buột, chứa URL có giá trị
Comment optional, yêu cầu không bắt buột, chứa nhiều dòng thông tin nhập vào
Gender required, yêu cầu bắt buột, chọn một tùy chọn

Trước tiên, chúng ta sẽ xem xét mã HTML thuần túy cho biểu mẫu:

Trường văn bản

Các trường name, emailwebsite là các yếu tố nhập văn bản và trường comment là một vùng văn bản. Mã HTML như sau:

Name: <input type="text" name="name">
E-mail: <input type="text" name="email">
Website: <input type="text" name="website">
Comment: <textarea name="comment" rows="5" cols="40"></textarea>

Các nút Radio

Các trường giới tính là các nút radio và mã HTML như sau:

Gender:
<input type="radio" name="gender" value="female">Female
<input type="radio" name="gender" value="male">Male
<input type="radio" name="gender" value="other">Other

Phần tử form

Mã HTML của biểu mẫu form như sau

<form method="post" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>">

Khi biểu mẫu được gửi, dữ liệu biểu mẫu được gửi với method = "post".

Biến $_SERVER["PHP_SELF"] là gì?

$_SERVER["PHP_SELF"] là một biến siêu toàn cục trả về tên tệp của tập lệnh hiện đang thực thi.

Vì vậy, $_SERVER["PHP_SELF"] sẽ gửi dữ liệu biểu mẫu đã gửi đến chính trang đó, thay vì chuyển sang một trang khác. Bằng cách này, người dùng sẽ nhận được thông báo lỗi trên cùng một trang với biểu mẫu.

Hàm htmlspecialchars() là gì?

Hàm htmlspecialchars() chuyển đổi các ký tự đặc biệt thành các thực thể HTML thông thường. Điều này có nghĩa là nó sẽ thay thế các ký tự đặc biệt HTML như @, #, $ ... . Điều này ngăn những kẻ tấn công khai thác mã bằng cách chèn mã HTML hoặc Javascript (Các cuộc tấn công Tập lệnh chéo trang web) trong các biểu mẫu.

Lưu ý quan trọng về biểu mẫu PHP


Biến $_SERVER["PHP_SELF"] có thể bị hacker sử dụng!

Nếu PHP_SELF được sử dụng trong trang của bạn thì người dùng có thể nhập dấu gạch chéo (/) rồi thực thi một số lệnh Cross Site Scripting (XSS).

Cross-site scripting (XSS) là một loại lỗ hổng bảo mật máy tính thường thấy trong các ứng dụng Web. XSS cho phép những kẻ tấn công đưa tập lệnh phía máy khách vào các trang Web được người dùng khác xem.

Giả sử chúng ta có biểu mẫu sau trong một trang có tên "test_form.php":

<form method="post" action="<?php echo $_SERVER["PHP_SELF"]; ?>">

Bây giờ, nếu người dùng nhập URL bình thường vào thanh địa chỉ như "http://www.example.com/test_form.php", thì đoạn mã trên sẽ được dịch thành:

<form method="post" action="test_form.php">

Tuy nhiên, hãy xem xét rằng người dùng nhập URL sau vào thanh địa chỉ:

http://www.example.com/test_form.php/%22%3E%3Cscript%3Ealert('hacked')%3C/script%3E

Trong trường hợp này, mã trên sẽ được dịch thành:

<form method="post" action="test_form.php/"><script>alert('hacked')</script>

Mã này thêm một thẻ tập lệnh và một lệnh cảnh báo. Và khi tải trang, mã JavaScript sẽ được thực thi (người dùng sẽ thấy một hộp cảnh báo). Đây chỉ là một ví dụ đơn giản và vô hại về cách khai thác biến PHP_SELF.

Hãy lưu ý rằng bất kỳ mã JavaScript nào cũng có thể được thêm vào bên trong thẻ <script>! Một tin tặc có thể chuyển hướng người dùng đến một tệp trên máy chủ khác và tệp đó có thể chứa mã độc hại có thể thay đổi các biến toàn cục hoặc gửi biểu mẫu đến một địa chỉ khác để lưu dữ liệu người dùng, chẳng hạn.

Làm thế nào để tránh bị khai thác biến $_SERVER ["PHP_SELF"]?


Chúng ta có thể tránh khai thác biến $_SERVER["PHP_SELF"] bằng cách sử dụng hàm htmlspecialchars().

Mã HTML form sẽ giống như sau:

<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">

Hàm htmlspecialchars() chuyển đổi các ký tự đặc biệt thành các thực thể HTML. Bây giờ nếu người dùng cố gắng khai thác biến PHP_SELF, nó sẽ dẫn đến kết quả sau:

<form method="post" action="test_form/&quot;&gt;&lt;script&gt;alert('hacked')&lt;/script&lt;">

Nỗ lực khai thác không thành công và không có tác hại nào được thực hiện!

Xác thực dữ liệu form với PHP


Điều đầu tiên chúng ta sẽ làm là chuyển tất cả các biến thông qua hàm htmlspecialchars() của PHP.

Khi chúng ta sử dụng hàm htmlspecialchars(); sau đó nếu người dùng cố gắng gửi nội dung sau trong trường văn bản:

<script>location.href('http://www.hacker.com')</script>

Điều này sẽ không được thực thi, vì nó sẽ được thể hiện dưới dạng mã thoát HTML, như thế này:

&lt;script&gt;location.href('http://www.hacker.com')&lt/script&gt;

Mã hiện an toàn để được hiển thị trên một trang hoặc bên trong e-mail.

Chúng ta cũng sẽ thực hiện hai việc nữa khi người dùng gửi biểu mẫu:

  • Loại bỏ các ký tự không cần thiết (thêm khoảng trắng, tab, dòng mới) khỏi dữ liệu đầu vào của người dùng (với hàm trim() của PHP)
  • Xóa dấu gạch chéo ngược (\) khỏi dữ liệu đầu vào của người dùng (với hàm dấu gạch chéo ngược () trong PHP)

Bước tiếp theo là tạo một hàm sẽ thực hiện tất cả việc kiểm tra cho chúng ta (điều này thuận tiện hơn nhiều so với việc viết đi viết lại cùng một đoạn mã).

Chúng ta sẽ đặt tên cho hàm là test_input().

Bây giờ, chúng ta có thể kiểm tra từng biến $_POST bằng hàm test_input() và tập lệnh như sau:

Ví dụ

Ví dụ

<?php
$name = $email = $website = $gender = $comment = "";
   
if($_SERVER['REQUEST_METHOD'] == 'POST'){
    $name = test_input($_POST['name']);
    $email = test_input($_POST['email']);
    $gender = test_input($_POST['gender']);
    $comment = test_input($_POST['comment']);
    $website = test_input($_POST['website']);    
}

function test_input($data){
    $data = trim($data);
    $data = addslashes($data);
    $data = htmlspecialchars($data);
    return $data;
}
?>

Xem kết quả

Lưu ý rằng khi bắt đầu tập lệnh, chúng ta kiểm tra xem biểu mẫu đã được gửi bằng cách sử dụng biến $_SERVER["REQUEST_METHOD"] hay chưa. Nếu REQUEST_METHODPOST, thì biểu mẫu đã được gửi, và nó sẽ được xác thực. Nếu nó chưa được gửi, thì bỏ qua xác thực và hiển thị một biểu mẫu trống.

Tuy nhiên, trong ví dụ trên, tất cả các trường đầu vào là tùy chọn. Tập lệnh hoạt động tốt ngay cả khi người dùng không nhập bất kỳ dữ liệu nào.

Bước tiếp theo là yêu cầu các trường nhập và tạo thông báo lỗi nếu cần.