Một trong lỗi kinh điển của SQL là lỗi MySql injection đây là một trong các lỗi cực kỳ nguy hiểm(mình sẽ nói về lỗi này vào một bài khác), và để hạn chế lỗi đó thì các bạn nên sử dụng cơ chế prepared SQL.
1, Cơ chế prepared SQL.
-Cơ chế này hoạt động như sau: Khi chúng ta viết câu truy vấn mà có dữ liệu động thì thay vì truyền trực tiếp tham số thì chúng ta sẽ thay các tham số đó bằng các biến ẩn danh, rồi sau đó chúng ta sẽ truyền các giá trị cho các biến ẩn danh đó và PHP sẽ prepared sao cho bảo mật nhất rồi mới chạy câu truy vấn.
2, Prepared bằng mysqli.
mysqli hướng thủ tục
-mysqli hướng thủ tục không hỗ trợ chúng ta prepared nhưng chúng ta hoàn toàn có thể dựa vào mysqli_stmt
trung gian để prepare.
VD:
// khởi tạo kết nối
$connect = mysqli_connect('localhost', 'root', '', 'db_tuts');
//Kiểm tra kết nối
if (!$connect) {
die('kết nối không thành công ' . mysqli_connect_error());
}
//câu truy vấn
$sql = "SELECT content FROM tbl_news WHERE id=? ";
//gán id
$id = 8;
//gán Mysqli sang mysqli_stmt
$stmt = mysqli_stmt_init($connect);
if (mysqli_stmt_prepare($stmt, $sql)) {
//tiến hành truyền dữ liệu vào biến ẩn danh
mysqli_stmt_bind_param($stmt, "i", $id);
//chạy câu truy vấn
mysqli_stmt_execute($stmt);
// gán dữ liệu trả về vào biến $data
mysqli_stmt_bind_result($stmt, $data);
//thực hiện fetch dữ liệu
mysqli_stmt_fetch($stmt);
//in ra kết quả trả về
printf('Result: %s', $data);
//close mysqli_stmt
mysqli_stmt_close($stmt);
}
//close mysqli
mysqli_close($connect);
mysqli hướng đối tượng
// khởi tạo kết nối
$connect = new mysqli('localhost','root','','db_tuts');
//Kiểm tra kết nối
if($connect->connect_error){
die('kết nối không thành công '.$connect->connect_error);
}
//câu truy vấn
$sql = "SELECT content FROM tbl_news WHERE id=?";
//set id
$id=8;
//prepare câu truy vấn
$stmt=$connect->prepare($sql);
//truyền data vào vào biến ẩn danh
$stmt->bind_param("i",$id);
// thực thi câu truy vấn
$stmt->execute();
//bind dữ liệu trả về vào biến data
$stmt->bind_result($data);
// fetch dữ liệu
$stmt->fetch();
//in ra dữ liệu
echo $data;
//ngắt kết nối
$connect->close();
-Trong đó: các ký tự như s,d,i có ý nghĩa như sau:
- i: interger
- d: double
- s: string
- b: blob
3, Prepared bằng PDO.
try {
// khởi tạo kết nối
$connect = new PDO('mysql:host=localhost;dbname=db_tuts', 'root', '');
$connect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//Câu truy vấn
$sql = "SELECT * FROM tbl_news WHERE id=:id";
//sét id
$id = 7;
//set truy vấn với prepare
$query = $connect->prepare($sql);
//gán thông số cho biến ẩn danh
$query->bindParam(':id', $id);
// thực hiện truy vấn
$query->execute();
//gán dữ liệu trả về
$result = $query;
//khởi tạo biến đếm $i
$i = 1;
// Lặp kết quả trả về
foreach ($result as $item) {
echo 'Dữ liệu thứ ' . $i . ' gồm: ' . $item['id'] . '-' . $item['title'] . '-' . $item['content'] . '<br/>';
$i++;
}
} catch (PDOException $e) {
//thất bại
die($e->getMessage());
}
4, Lời kết.
-Như vậy mình đã giới thiệu các prepare SQL bằng 3 cách, các bạn cũng nên sử dụng cách này trong các dự án vì nó tránh được lỗi mysqli injection.
Đăng ký nhận tin.
Chúng tôi chỉ gửi tối đa 2 lần trên 1 tháng. Tuyên bố không spam mail!
Bài viết hay.
Cảnh Linh
6 năm trước