1. Sự an toàn khi xử lý biểu mẫu trong PHP

Chúng ta hãy nghĩ đến sự an toàn khi xử lý các biểu mẫu. Việc an toàn cho dữ liệu cũng như 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 hay thư rác.

Validation giúp kiểm tra thông tin đưa vào từ form như input, number, nút radio,… Với các quy tắc nhập dữ liệu do ta đặt ra. Dữ liệu đầu vào của người dùng nhập vào đôi khi có thể sai như email không có @, số điện thoại lại có ký tự đặc biệt,… Để khắc phục vấn đề này , PHP sẽ xác thực dữ liệu ở phía máy chủ, được gửi bằng biểu mẫu HTML và được gọi là Validation form – xác thực biểu mẫu.

2. Xây dựng form HTML cơ bản

Chúng ta sẽ xây dựng một form HTML cơ bản để học được bài hôm nay. Hình ảnh như bên dưới. Các bạn có thể tự code theo hình này nhé!

Để xây dựng được form này ta sẽ có:

  • Phần tử gửi biểu mẫu:
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
  • Các trường văn bản:
Name: <input type="text" name="name">
E-mail: <input type="text" name="email">
SDT: <input type="text" name="number">
Website: <input type="text" name="website">
Comment: <textarea name="comment" rows="5" cols="40"></textarea>
  • Các nút radio:
<input type="radio" name="gender" value="female">Female
<input type="radio" name="gender" value="male">Male
<input type="radio" name="gender" value="other">Other

Ta phải xác thực cho biểu mẫu trên như sau:

  • Tên : bắt buộc và chỉ có chứa chữ cái hoặc khoảng trắng.
  • Email : bắt buộc và phải chứa @.
  • Website : không bắt buộc nhưng nếu có phải có thanh URL hợp lệ.
  • Nhận xét : nhập nhiều dòng.
  • Giới tính : bắt buộc phải chọn một.

3. Các kiểu Validate thường gặp

3.1. Validate chuỗi rỗng

Với kiểu này ta sẽ xác thực người dùng có nhập thông tin hay không. Nếu đã nhập rồi thì ta sẽ cho phép người dùng gửi dữ liệu, còn nếu chưa ta sẽ báo lỗi cho người dùng để họ nhập lại.

Ví dụ: ở các ví dụ của phần này ta sẽ lấy luôn form đã làm ở trên để làm ví dụ luôn nhé. Ta sẽ thêm code PHP như sau:

<?php
if(isset($_POST['text'])) {
    $name = $_POST ["name"];
    if (empty($name)) 
    {  
        echo "Trường này là bắt buộc.";           
    }
    else 
    {
        echo $name; 
    }
}
?>

3.2. Validate chuỗi

Kiểu này sẽ chỉ cho ta nhập bảng chữ cái hoặc khoảng trắng.

Vẫn là form ví dụ trên ta sẽ thay code PHP như sau:

if (!preg_match ("/^[a-zA-z]*$/",$name)) 
    {  
        echo "Chỉ cho phép nhập chữ cái và khoảng trắng.";           
    }
    else 
    {
        echo $name; 
    }

3.3. Validate số điện thoại

Trường hợp này sẽ chỉ cho ta nhập số.

Ví dụ:

$number = $_POST ["number"];
    if (!preg_match ("/^[0-9]*$/",$number)) 
    {  
        echo "Vui lòng nhập số.";           
    }
    else 
    {
        echo $number; 
    }

3.4. Validate email

Kiểu này sẽ kiểm tra cho ta email có hợp lệ không – ở đây sẽ phải chứa @

Ví dụ:

$email = $_POST ["email"];
    $pattern = "^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$^";  
    if (!preg_match ($pattern, $email) )
    {  
        echo "Vui lòng địa chỉ Email.";           
    }
    else 
    {
        echo $email; 
    }

3.5. Validate URL

Kiểm tra nếu có URL phải là thanh URL hợp lệ

Ví dụ:

$webUrl = $_POST ["webUrl"];
    $patternUrl = "/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i";
    if (!preg_match($patternUrl, $webUrl)) 
    {  
        echo "Yêu cầu nhập chính xác đường dẫn.";           
    }
    else 
    {
        echo $webUrl; 
    }

3.6. Validate kiểm tra độ dài

Ở đây ta sẽ kiểm tra độ dài dữ liệu người dùng nhập vào. Ví dụ như số điện thoại cần tối thiểu 10 ký tự, hay họ tên cần tối thiểu 6 ký tự,… Ta sẽ dùng hàm strlen để đếm ký tự nhập vào sau đó so sánh với số ký tự điều kiện. Ta dùng if…else thông báo lỗi và in ra kết quả.

Ví dụ:

$name = $_POST ["name"];
    $length  =  strlen($name); 
    if ($length < 6) 
    {  
        echo "Tên cần tối thiểu 6 ký tự.";           
    }
    else 
    {
        echo $name; 
    }

4. Biến $_SERVER[“PHP_SELF”] và hàm htmlspecialchars() trong PHP

4.1. Giới thiệu về biến $_SERVER[“PHP_SELF”] và hàm htmlspecialchars()

Biến $_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 đang được thực thi. Vì vậy mà biến $_SERVER[“PHP_SELF”] sẽ gửi dữ liệu biểu mẫu đã được gửi đến chính trang của nó, thay vì việc ta phải chuyển sang một trang khác.

Hàm htmlspecialchars() chuyển đổi các ký tự đặc biệt thành các thực thể HTML. Có nghĩa nó sẽ thay thế các ký tự HTML như < > . Điều này sẽ ngăn những kẻ tấn công khai thác mã bằng việc chèn mã HTML hay Javascript trong các biểu mẫu.

4.2. Một số lưu ý:

Biến $_SERVER[“PHP_SELF”] có thể sẽ bị tin tặc sử dụng. Nếu PHP_SELF được sử dụng trong trang thì người dùng có thể nhập dấu gạch chéo / rồi thực thi một số câu lệnh XSS(Cross Site Scripting). Đây là một loại lỗ hổng bảo mật máy tính hay xuất hiện trên những ứng dụng web. XSS cho phép kẻ tấn công đưa tập lệnh máy khác vào trang web được người dùng khác xem.

Ví dụ:

Ta tạo một biểu mẫu trong file test.php

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

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

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

Nhưng nếu ta nhập địa chỉ này thì sao: http://www.example.com/test_form.php/%22%3E%3Cscript%3Ealert(‘hacked’)%3C/script%3E

Đoạn mã sẽ được dịch thành:

<form method=”post” action=”test_form.php/”><script>alert(‘hacked’)</script>

Đây chỉ là một ví dụ vô hại về biến PHP_SELF. Hãy lưu ý rằng bất kỳ mã JS nào cũng có thể được thêm trong thẻ <script>. Tin tặc có thể chuyển hướng người dùng đến một địa chỉ khác để lưu dữ liệu người dùng, …

4.3. Làm sao để tránh bị khai thác $_SERVER[“PHP_SELF”]

Ta có thể tránh bị khai thác $_SERVER[“PHP_SELF”] bằng cách sử dụng hàm htmlspecialchars(). Ta sẽ có mã biểu mẫu như sau:

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

Như ta đã biết hàm htmlspecialchars() sẽ chuyển đổi ký tự đặc biệt thành thực thể HTML. Nếu có người khai thác biến PHP_SELF thì sẽ dẫn đến kết quả:

<form method=”post” action=”test_form.php/&quot;&gt;&lt;script&gt;alert(‘hacked’)&lt;/script&gt;”>

Tin tặc sẽ khai thác không thành công và không có cách nào thực hiện được.

5. Xác thực dữ liệu biểu mẫu với PHP

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

Ta sẽ thực hiện 2 công việc nữa khi người dùng gửi biểu mẫu:

  • Loại bỏ tất cả các ký tự không cần thiết khỏi dữ liệu đầu vào của người dùng. Ta sẽ dùng hàm trim()
  • Xóa dấu gạch chéo ngược \ khỏi dữ liệu đầu vào của người dùng

Tiếp theo là ta tạo một hàm sẽ thực hiện tất cả công việc kiểm tra cho chúng ta(giúp ta không tốn thời gian viết đi viết lại một đoạn mã). Cuối cùng là ta có thể kiểm tra từng biến $_POST bằng hàm vừa tạo.

Ví dụ:

<?php
$name = $email = $gender = $comment = $website = "";

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

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