2013-08-25 46 views
11

Tôi đang học cách tránh tiêm SQL và tôi hơi bối rối.bind_param thực hiện điều gì?

Khi sử dụng bind_param, tôi không hiểu mục đích. Trên trang hướng dẫn, tôi thấy ví dụ này:

$stmt = mysqli_prepare($link, "INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)"); 
mysqli_stmt_bind_param($stmt, 'sssd', $code, $language, $official, $percent); 

$code = 'DEU'; 
$language = 'Bavarian'; 
$official = "F"; 
$percent = 11.2; 

Bây giờ, giả sử những 4 biến là sử dụng đầu vào, tôi không hiểu làm thế nào điều này ngăn cản tiêm SQL. Theo sự hiểu biết của tôi, họ vẫn có thể nhập bất cứ điều gì họ muốn ở đó.

Tôi cũng không thể tìm thấy giải thích cho số 'sssd' trong đó. Nó làm gì? Đó có phải là điều làm cho nó an toàn không?

Câu hỏi cuối cùng: Tôi đã đọc một câu hỏi khác mà mysqli_real_escape_string không còn được dùng nữa, nhưng không được nói trong hướng dẫn sử dụng. Làm thế nào là nó không được chấp nhận? Nó có thể không thoát khỏi những nhân vật đặc biệt nữa vì một lý do nào đó không?

Lưu ý: Câu hỏi này giải thích những gì bind_param làm, nhưng tôi vẫn không hiểu tại sao nó an toàn hơn hoặc được bảo vệ hơn. Bind_param explanation

+6

'sssd' chuyển thành chuỗi, chuỗi, chuỗi, gấp đôi. 'Theo hiểu biết của tôi, họ vẫn có thể nhập bất cứ điều gì họ muốn ở đó.' Đúng. Nhưng không có SQL được phân tích cú pháp trong bốn biến đó. –

+1

Trên liên kết bạn đã gửi, bạn quên đọc http://www.php.net/manual/en/mysqli-stmt.bind-param.php chi tiết tại 'loại Một chuỗi chứa một hoặc nhiều ký tự chỉ định các loại cho các biến liên kết tương ứng: ' – Prix

+1

@DaveChen" Không có SQL được phân tích cú pháp "Điều đó có nghĩa là chúng vẫn có thể chèn SQL, nó sẽ không được đọc là SQL, đúng không? Điều đó có nghĩa rằng nếu tôi không có xác nhận mẫu, họ chỉ có thể nhập các lệnh SQL vào cơ sở dữ liệu của tôi/vào trường, nhưng nó sẽ không quan trọng vì SQL không được phân tích cú pháp? – EveyPortman

Trả lời

12

Bây giờ, giả sử những 4 biến là sử dụng đầu vào, tôi không hiểu cách này ngăn chặn tiêm SQL. Theo hiểu biết của tôi, họ vẫn có thể nhập bất kỳ thứ gì họ muốn vào đó.

Nguyên tắc chính là sử dụng câu lệnh chuẩn bị được thiết kế để gửi truy vấn an toàn tới máy chủ db. where khoản) để kiểm tra tính hợp lệ của truy vấn trước khi sử dụng bất kỳ tham số nào.

Từ câu hỏi này: PDO sends raw query to MySQL while Mysqli sends prepared query, both produce the same result

$stmt = $mysqli->prepare("SELECT * FROM users WHERE username =?")) { 
$stmt->bind_param("i", $user); 
$user = "''1''"; 

các bản ghi máy chủ:

130802 23:39:39 175 Connect ****@localhost on testdb 
    175 Prepare SELECT * FROM users WHERE username =? 
    175 Execute SELECT * FROM users WHERE username =0 
    175 Quit 

Bởi Sử dụng tuyên bố chuẩn bị, máy chủ db sẽ kiểm tra các truy vấn mà không có tham số, ở giai đoạn này, các lỗi có thể được phát hiện trước khi ràng buộc bất kỳ tham số nào, sau đó, nếu truy vấn hợp lệ, các tham số cũng sẽ được gửi đến máy chủ để hoàn tất truy vấn.

Từ PHP Manual http://php.net/manual/en/mysqli.quickstart.prepared-statements.php:

Thoát và SQL injection

biến ràng buộc sẽ được thoát tự động bởi máy chủ. Máy chủ chèn các giá trị được thoát của chúng tại các vị trí thích hợp vào mẫu tuyên bố trước khi thực thi. Một gợi ý phải được cung cấp cho máy chủ cho loại biến bị ràng buộc, để tạo một chuyển đổi thích hợp. Xem hàm mysqli_stmt_bind_param() để biết thêm thông tin .

..

Tôi cũng không thể tìm thấy một lời giải thích cho 'sssd' trong đó. Nó làm gì?Đó có phải là điều làm cho nó an toàn không?

Câu trả lời là ở đây: http://php.net/manual/en/mysqli-stmt.bind-param.php

i 
corresponding variable has type integer 

d 
corresponding variable has type double 

s 
corresponding variable has type string 

b 
corresponding variable is a blob and will be sent in packets 

Câu hỏi cuối cùng: Tôi đọc trên một câu hỏi rằng mysqli_real_escape_string bị phản đối, nhưng nó không nói rằng trong hướng dẫn. Làm thế nào là nó không được chấp nhận? Nó có thể không thoát khỏi các ký tự đặc biệt nữa vì một số lý do?

Bạn có thể tham khảo không? Tôi nghĩ bạn đã hiểu lầm (mysql_real_escape_string())

+0

Cảm ơn, và có, tôi phải đọc mysql như msqli ở đâu đó. – EveyPortman

+0

@EveyPortman xin lưu ý rằng câu trả lời này là sai. –

+3

@YourCommonSense: đăng câu trả lời đúng và đề cập đến những gì sai trong câu trả lời của tôi. –

10

Bằng cách sử dụng câu lệnh đã chuẩn bị, bạn đang tách truy vấn SQL khỏi dữ liệu do người dùng nhập. Thay vì dữ liệu đầu vào, bạn đặt phần giữ chỗ ('?' Char) trong truy vấn SQL của mình. Sau đó, bạn gửi truy vấn đến máy chủ DBMS (ví dụ: MySQL) bằng phương tiện "mysqli :: prepare". Vì vậy, máy chủ kiểm tra xem mọi thứ có ổn không và nếu có, nó sẽ đợi dữ liệu đầu vào. Bởi bây giờ nó đã biết truy vấn của bạn. Chỉ cần đợi dữ liệu đầu vào để liên kết với truy vấn.

Tại thời điểm này, "bind_param" đi vào hoạt động, trình giữ chỗ ràng buộc với dữ liệu do người dùng nhập. Lưu ý rằng bind_param chỉ liên kết dữ liệu với trình giữ chỗ để không thay đổi truy vấn. Vì vậy, không có cách nào để thay đổi truy vấn SQL gốc, vì nó đã được gửi đến máy chủ bằng phương tiện chuẩn bị và bởi vì bạn đang gửi truy vấn SQL và dữ liệu đầu vào riêng biệt để dữ liệu người dùng nhập vào không thể can thiệp vào truy vấn.

ANYWAY ...

Mục đích thực tế để sử dụng một tuyên bố chuẩn bị trong SQL là để cắt giảm chi phí của các truy vấn chế biến, KHÔNG để tách dữ liệu từ truy vấn. Đó là cách nó được sử dụng hiện nay, không phải cách nó được thiết kế để được sử dụng ngay từ đầu.

'sssd' là viết tắt của "string", "string", "string" và "double". Trong thực tế: $ code là một chuỗi, $ ngôn ngữ là một chuỗi, $ chính thức là một chuỗi và $ phần trăm là một loại đôi.

mysqli_real_escape_string không được dùng nữa nhưng mysql_real_escape_string không được dùng nữa (cái đầu tiên là mysqlI, nơi tôi viết tắt là "cải tiến").

Các vấn đề liên quan