PHP VÀ MYSQL
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
Dự án mới của mình là gamehow.net, mời anh em ghé thăm và góp ý ạ.

Bài 08: Cơ chế prepared câu SQL trong PHP

Ở một số website code bằng PHP thuần thường mắc phải lỗi SQL injection là do lập trình viên không biết đến lỗi này hoặc biết nhưng không tìm cách khắc phục nó. Trước đây chúng ta hay sử dụng hàm addslashes() trong PHP để khắc phục nhưng bây giờ các thư viện xử lý database cũng đã đưa ra cơ chế prepared nhằm hạn chế lỗi bảo mật này.

1. Cơ chế prepared câu SQL

Trước đây nếu truyền tham số vào câu truy vấn thì chúng ta hay thực hiện như ví dụ dưới đây:

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

$username = $_POST['username'];
$password = $_POST['password'];

$sql = "select * from users where username = '$username' and password = '$password'";

Đây là cách gán chuỗi thông thường và sẽ mắc phải lỗi SQL injection. Ta có một cách khác sẽ khắc phục được phần nào đó là sử dụng hàm addslashes().

$username = addslashes($_POST['username']);
$password = addslashes($_POST['password']);

$sql = "select * from users where username = '$username' and password = '$password'";

Bây giờ người ta đã không sử dụng cách trên nữa mà sử dụng chức năng có sẵn trong các thư viện MySQLi và PDO. Mỗi thư viện có cách thể hiện khác nhau nhưng chúng đều có chung một quy tắc đó là:

  • Chúng ta đưa vào một câu truy vấn với các tham số là một ẩn danh
  • Chúng ta truyền vào giá trị tương ứng cho các ẩn danh đó
  • PHP sẽ dựa vào thư tự các tham số ẩn danh và các giá trị để repared sao bảo mật nhất.
  • Cuối cùng sẽ thực thi câu truy vấn.
  • Khi bạn đã khai báo các tham số lần đầu rồi và sau đó muốn sử dụng tiếp thì không cần phải khai báo nữa. Đây cũng chính là lợi thế của cơ chế prepared trong PHP.

Để dễ hiểu hơn thì bạn nên đọc qua phần 2 và phần 3 dưới đây.

2. Prepared câu SQL trong MySQLi

Chúng ta chỉ thực hiện Prepared trong trường hợp sử dụng MySQLi Object-oriented.

Các tham số truyền vào sở là các dấu chấm hỏi ?, đây chính là tham số ẩn danh.

// Kết nối
$conn = new mysqli('localhost', 'root', 'vertrigo', 'FreetutsDemo');

// kiểm tra kết nối
if ($conn->connect_error) {
    die("Kết nối thất bại: " . $conn->connect_error);
}

// Câu SQL
$sql = "INSERT INTO News (title, content) VALUES (?, ?)";

// Tạo đối tượng repared
$stmt = $conn->prepare($sql);

// Gán giá trị vào các tham số ẩn
$stmt->bind_param("ss", $title, $content);

// Thực thi câu truy vấn lần 1
$title = 'Tiêu đề 1';
$content = 'Nội dung 1';
$stmt->execute();

// Thực thi câu truy vấn lần 2
$title = 'Tiêu đề 2';
$content = 'Nội dung 2';
$stmt->execute();

echo "Thêm thành công!";

// Giải phóng và ngắt kết nối
$stmt->close();
$conn->close();

Trong đoạn code trên có nhiều vướng mắc mà có lẽ bạn sẽ không hiểu nên mình sẽ giải thích thêm.

Thứ nhất: Câu SQL

$sql = "INSERT INTO News (title, content) VALUES (?, ?)";

Trong câu SQL này thì hai dấu ? chính là hai tham số ẩn danh.

Thứ hai: Thực hiện bind data

$stmt->bind_param("ss", $title, $content);

Giá trị đầu tiên là hai chữ ss, đây chính là khai báo dữ liệu cho hai tham số ẩn danh ở trên. Ý nghĩa như sau:

  • i: interger
  • d: double
  • s: string
  • b: blob

Còn hai tham số $title$content chính là hai tham số dạng tham chiếu nên dù chưa được khai báo nhưng vẫn không bị lỗi.

Những đoạn code còn lại quá đơn giản nên mình không giải hích thêm.

3. Prepared câu SQL trong PDO

Với PDO thì cú pháp có hơi khác chút xíu đó là tham số ẩn không phải là dấu hỏi nữa mà là ở dạng :varname.

try {
    // Kết nối
    $conn = new PDO("mysql:host=localhost;dbname=FreetutsDemo", 'root', 'vertrigo');
    // Khai baso exception
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // prepare sql and bind parameters
    $stmt = $conn->prepare("INSERT INTO News (title, content) VALUES (:title, :content)");
    $stmt->bindParam(':title', $title);
    $stmt->bindParam(':content', $content);

    // Thêm lần 1
    $title = 'Tiêu đề 1';
    $content = 'Nội dung 1';
    $stmt->execute();

    // Thêm lần 2
    $title = 'Tiêu đề 2';
    $content = 'Nội dung 2';
    $stmt->execute();

    echo "Thao tác thành công!";
} 
catch (PDOException $e) {
    echo "Error: " . $e->getMessage();
}

// Ngắt kết nối
$conn = null;

Giải thích như phần MySQLi nên nếu ban không hiểu thì hãy đọc lại phần 2 nhé.

4. Lời kết

Như vậy là mình đã giới thiệu cách sử dụng cơ chế Prepared câu SQL trong PHP bằng hai thư viện MySQli và PDO, đây là cách chúng ta nên sư dụng để thực thi các câu truy vấn khi làm ứng dụng thực tế bởi nó tránh được lỗi SQL Injection. Bài tiếp theo chúng ta sẽ tìm hiểu cách lấy dữ liệu từ MySQL trong PHP.

Tổng hợp dữ liệu trong bài:

Cùng chuyên mục:

Hàm key_exists() trong PHP

Hàm key_exists() trong PHP

Cách sử dụng key_exists() trong PHP

Hàm mysqli_fetch_row() trong PHP

Hàm mysqli_fetch_row() trong PHP

Cách sử dụng mysqli_fetch_row() trong PHP

Hàm end() trong PHP

Hàm end() trong PHP

Cách sử dụng end() trong PHP

Hàm mysqli_field_count() trong PHP

Hàm mysqli_field_count() trong PHP

Cách sử dụng mysqli_field_count() trong PHP

Hàm count() trong PHP

Hàm count() trong PHP

Cách sử dụng count() trong PHP

Hàm mysqli_field_seek() trong PHP

Hàm mysqli_field_seek() trong PHP

Cách sử dụng mysqli_field_seek() trong PHP

Hàm compact() trong PHP

Hàm compact() trong PHP

Cách sử dụng compact() trong PHP

Hàm mysqli_field_tell() trong PHP

Hàm mysqli_field_tell() trong PHP

Cách sử dụng mysqli_field_tell() trong PHP

Hàm array_values() trong PHP

Hàm array_values() trong PHP

Cách sử dụng array_values() trong PHP

Hàm mysqli_free_result() trong PHP

Hàm mysqli_free_result() trong PHP

Cách sử dụng mysqli_free_result() trong PHP

Hàm array_unshift() trong PHP

Hàm array_unshift() trong PHP

Cách sử dụng array_unshift() trong PHP

Hàm mysqli_get_charset() trong PHP

Hàm mysqli_get_charset() trong PHP

Cách sử dụng mysqli_get_charset() trong PHP

Hàm array_shift() trong PHP

Hàm array_shift() trong PHP

Cách sử dụng array_shift() trong PHP

Hàm mysqli_get_client_stats() trong PHP

Hàm mysqli_get_client_stats() trong PHP

Cách sử dụng mysqli_get_client_stats() trong PHP

Hàm array_unique() trong PHP

Hàm array_unique() trong PHP

Cách sử dụng array_unique() trong PHP

Hàm mysqli_get_client_version() trong PHP

Hàm mysqli_get_client_version() trong PHP

Cách sử dụng mysqli_get_client_version() trong PHP

Hàm array_uintesect() trong PHP

Hàm array_uintesect() trong PHP

Cách sử dụng array_uintesect() trong PHP

Hàm mysqli_get_connection_stats() trong PHP

Hàm mysqli_get_connection_stats() trong PHP

Cách sử dụng mysqli_get_connection_stats() trong PHP

Hàm array_sum() trong PHP

Hàm array_sum() trong PHP

Cách sử dụng array_sum() trong PHP

Hàm mysqli_get_host_info() trong PHP

Hàm mysqli_get_host_info() trong PHP

Cách sử dụng mysqli_get_host_info() trong PHP

Top