Безопасно
query.SQL.Text := 'select * from table_name where name=:Name';
Този код е безопасен, защото използвате параметри.
Параметрите винаги са безопасни от SQL инжекция.
Опасно
var Username: string;
...
query.SQL.Text := 'select * from table_name where name='+ UserName;
Не е безопасно, защото потребителското име може да бъде name; Drop table_name;
В резултат на това се изпълнява следната заявка.
select * from table_name where name=name; Drop table_name;
Също Опасно
var Username: string;
...
query.SQL.Text := 'select * from table_name where name='''+ UserName+'''';
Защото, ако потребителското име е ' or (1=1); Drop Table_name; --
Това ще доведе до следната заявка:
select * from table_name where name='' or (1=1); Drop Table_name; -- '
Но този код е безопасен
var id: integer;
...
query.SQL.Text := 'select * from table_name where id='+IntToStr(id);
Тъй като IntToStr()
ще приема само цели числа, така че по този начин в низа на заявката не може да бъде инжектиран SQL код, а само числа (което е точно това, което искате и следователно е разрешено)
Но искам да правя неща, които не могат да се правят с параметри
Параметрите могат да се използват само за стойности. Те не могат да заменят имена на полета или имена на таблици. Така че, ако искате да изпълните тази заявка
query:= 'SELECT * FROM :dynamic_table '; {doesn't work}
query:= 'SELECT * FROM '+tableName; {works, but is unsafe}
Първата заявка е неуспешна, защото не можете да използвате параметри за имена на таблици или полета.
Втората заявка не е безопасна, но е единственият начин, по който това може да се направи.
Как да останете в безопасност?
Трябва да проверите низа tablename
срещу списък с одобрени имена.
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;
...
Това е единственият начин за това, който знам.
BTW Вашият оригинален код има грешка:
query.SQL.Text := 'select * from table_name where name=:Name where id=:ID';
Трябва да е
query.SQL.Text := 'select * from table_name where name=:Name and id=:ID';
Не можете да имате две where
е в една (под)заявка