Bezpečné
query.SQL.Text := 'select * from table_name where name=:Name';
Tento kód je bezpečný, protože používáte parametry.
Parametry jsou vždy v bezpečí před vkládáním SQL.
Nebezpečné
var Username: string;
...
query.SQL.Text := 'select * from table_name where name='+ UserName;
Není bezpečné, protože Uživatelské jméno může být name; Drop table_name;
Výsledkem je provedení následujícího dotazu.
select * from table_name where name=name; Drop table_name;
Také Nebezpečné
var Username: string;
...
query.SQL.Text := 'select * from table_name where name='''+ UserName+'''';
Protože pokud je uživatelské jméno ' or (1=1); Drop Table_name; --
Výsledkem bude následující dotaz:
select * from table_name where name='' or (1=1); Drop Table_name; -- '
Tento kód je však bezpečný
var id: integer;
...
query.SQL.Text := 'select * from table_name where id='+IntToStr(id);
Protože IntToStr()
bude přijímat pouze celá čísla, takže tímto způsobem nelze do řetězce dotazu vložit žádný kód SQL, pouze čísla (což je přesně to, co chcete, a proto je povoleno)
Ale já chci dělat věci, které nelze dělat s parametry
Parametry lze použít pouze pro hodnoty. Nemohou nahradit názvy polí ani názvy tabulek. Pokud tedy chcete provést tento dotaz
query:= 'SELECT * FROM :dynamic_table '; {doesn't work}
query:= 'SELECT * FROM '+tableName; {works, but is unsafe}
První dotaz selže, protože nemůžete použít parametry pro názvy tabulek nebo polí.
Druhý dotaz není bezpečný, ale je to jediný způsob, jak to lze provést.
Jak zůstat v bezpečí?
Musíte zkontrolovat řetězec tablename
proti seznamu schválených jmen.
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;
...
To je jediný způsob, jak to udělat, o kterém vím.
BTW Váš původní kód obsahuje chybu:
query.SQL.Text := 'select * from table_name where name=:Name where id=:ID';
Mělo by být
query.SQL.Text := 'select * from table_name where name=:Name and id=:ID';
Nemůžete mít dvě where
's v jednom (pod)dotazu