Safe
query.SQL.Text := 'select * from table_name where name=:Name';
Mã này là an toàn vì bạn đang sử dụng các thông số.
Các tham số luôn an toàn với SQL injection.
không an toàn
var Username: string;
...
query.SQL.Text := 'select * from table_name where name='+ UserName;
là không an toàn vì Tên truy cập có thể là name; Drop table_name;
Hệ quả là các truy vấn sau đây được thực thi.
select * from table_name where name=name; Drop table_name;
Cũng không an toàn
var Username: string;
...
query.SQL.Text := 'select * from table_name where name='''+ UserName+'''';
Bởi vì nó nếu username là ' or (1=1); Drop Table_name; --
Nó sẽ dẫn đến việc truy vấn sau đây:
select * from table_name where name='' or (1=1); Drop Table_name; -- '
Nhưng mã này là an toàn
var id: integer;
...
query.SQL.Text := 'select * from table_name where id='+IntToStr(id);
Vì IntToStr()
sẽ chỉ chấp nhận số nguyên nên không có mã SQL có thể được tiêm vào chuỗi truy vấn theo cách này, chỉ số (đó là chính xác những gì bạn muốn và do đó cho phép)
Nhưng tôi muốn làm những thứ không thể thực hiện được với thông số
Chỉ có thể sử dụng thông số cho giá trị. Họ không thể thay thế tên trường hoặc tên bảng. Vì vậy, nếu bạn muốn thực hiện truy vấn này
query:= 'SELECT * FROM :dynamic_table '; {doesn't work}
query:= 'SELECT * FROM '+tableName; {works, but is unsafe}
Truy vấn đầu tiên không thành công vì bạn không thể sử dụng tham số cho tên bảng hoặc trường.
Truy vấn thứ hai là không an toàn nhưng là cách duy nhất điều này có thể được thực hiện.
Làm thế nào để bạn được an toàn?
Bạn phải kiểm tra chuỗi tablename
đối với danh sách các tên được phê duyệt.
Const
ApprovedTables: array[0..1] of string = ('table1','table2');
procedure DoQuery(tablename: string);
var
i: integer;
Approved: boolean;
query: string;
begin
Approved:= false;
for i:= lo(ApprovedTables) to hi(ApprovedTables) do begin
Approved:= Approved or (lowercase(tablename) = ApprovedTables[i]);
end; {for i}
if not Approved then exit;
query:= 'SELECT * FROM '+tablename;
...
Đó là cách duy nhất để làm điều này, mà tôi biết.
BTW mã ban đầu của bạn có một lỗi:
query.SQL.Text := 'select * from table_name where name=:Name where id=:ID';
Nên
query.SQL.Text := 'select * from table_name where name=:Name and id=:ID';
Bạn không thể có hai where
's trong một (sub) truy vấn
cảm ơn Johan. Tôi đã sửa câu hỏi + 1 – RBA
+1 để bao gồm nhiều trường hợp –
Nhưng bạn vẫn có thể tiêm tham số SQL bằng 'name; Thả table_name; 'nếu nó được người dùng nhập vào trong loại hộp nhập đó –