Ý tưởng rất đơn giản - truy vấn và các dữ liệu được gửi đến máy chủ cơ sở dữ liệu riêng biệt .
Đó là tất cả.
Nguyên nhân của vấn đề tiêm SQL là trong việc trộn mã và dữ liệu.
Trong thực tế, truy vấn SQL của chúng tôi là một chương trình hợp pháp . Và chúng tôi đang tạo ra một chương trình như vậy một cách linh hoạt, thêm một số dữ liệu một cách nhanh chóng. Do đó, dữ liệu có thể can thiệp vào mã chương trình và thậm chí thay đổi nó, vì mọi ví dụ tiêm SQL đều hiển thị nó (tất cả các ví dụ trong PHP / Mysql):
$expected_data = 1;
$query = "SELECT * FROM users where id=$expected_data";
sẽ tạo ra một truy vấn thông thường
SELECT * FROM users where id=1
trong khi mã này
$spoiled_data = "1; DROP TABLE users;"
$query = "SELECT * FROM users where id=$spoiled_data";
sẽ tạo ra một chuỗi độc hại
SELECT * FROM users where id=1; DROP TABLE users;
Nó hoạt động vì chúng tôi đang thêm dữ liệu trực tiếp vào phần thân chương trình và nó trở thành một phần của chương trình, do đó dữ liệu có thể thay đổi chương trình và tùy thuộc vào dữ liệu được truyền, chúng tôi sẽ có đầu ra thông thường hoặc users
xóa bảng .
Mặc dù trong trường hợp các tuyên bố đã được chuẩn bị, chúng tôi không thay đổi chương trình của mình, nó vẫn còn nguyên vẹn
Đó là điểm chính.
Chúng tôi đang gửi một chương trình đến máy chủ đầu tiên
$db->prepare("SELECT * FROM users where id=?");
trong đó dữ liệu được thay thế bởi một số biến được gọi là tham số hoặc giữ chỗ.
Lưu ý rằng chính xác cùng một truy vấn được gửi đến máy chủ, không có bất kỳ dữ liệu nào trong đó! Và sau đó chúng tôi sẽ gửi dữ liệu với yêu cầu thứ hai , về cơ bản được tách ra khỏi chính truy vấn:
$db->execute($data);
vì vậy nó không thể thay đổi chương trình của chúng tôi và gây hại.
Khá đơn giản - phải không?
Điều duy nhất tôi phải thêm luôn luôn bị bỏ qua trong mọi hướng dẫn:
Các câu lệnh được chuẩn bị có thể chỉ bảo vệ các dữ liệu bằng chữ , nhưng không thể được sử dụng với bất kỳ phần truy vấn nào khác.
Vì vậy, một khi chúng ta phải thêm, giả sử, một định danh động - ví dụ như tên trường - các câu lệnh được chuẩn bị không thể giúp chúng ta. Tôi đã giải thích vấn đề gần đây , vì vậy tôi sẽ không lặp lại.