Bezpieczny
query.SQL.Text := 'select * from table_name where name=:Name';
Ten kod jest bezpieczny, ponieważ używasz parametrów.
Parametry są zawsze bezpieczne przed wstrzyknięciem SQL.
Niebezpieczne
var Username: string;
...
query.SQL.Text := 'select * from table_name where name='+ UserName;
Jest niebezpieczny, ponieważ nazwa użytkownika może być name; Drop table_name;
Powoduje to wykonanie następującego zapytania.
select * from table_name where name=name; Drop table_name;
Również Niebezpieczne
var Username: string;
...
query.SQL.Text := 'select * from table_name where name='''+ UserName+'''';
Ponieważ to, jeśli nazwa użytkownika to ' or (1=1); Drop Table_name; --
Spowoduje to następujące zapytanie:
select * from table_name where name='' or (1=1); Drop Table_name; -- '
Ale ten kod jest bezpieczny
var id: integer;
...
query.SQL.Text := 'select * from table_name where id='+IntToStr(id);
Ponieważ IntToStr()
przyjmie tylko liczby całkowite, więc żaden kod SQL nie może zostać w ten sposób wstrzyknięty do ciągu zapytania, tylko liczby (co jest dokładnie tym, czego chcesz, a zatem jest dozwolone)
Ale chcę robić rzeczy, których nie można zrobić za pomocą parametrów
Parametrów można używać tylko jako wartości. Nie mogą zastąpić nazw pól ani nazw tabel. Więc jeśli chcesz wykonać to zapytanie
query:= 'SELECT * FROM :dynamic_table '; {doesn't work}
query:= 'SELECT * FROM '+tableName; {works, but is unsafe}
Pierwsze zapytanie kończy się niepowodzeniem, ponieważ nie można użyć parametrów dla nazw tabel lub pól.
Drugie zapytanie jest niebezpieczne, ale jest to jedyny sposób, w jaki można to zrobić.
Jak zachować bezpieczeństwo?
Musisz sprawdzić ciąg tablename
z listą zatwierdzonych nazwisk.
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 jedyny sposób na zrobienie tego, jaki znam.
BTW Twój oryginalny kod zawiera błąd:
query.SQL.Text := 'select * from table_name where name=:Name where id=:ID';
Powinien być
query.SQL.Text := 'select * from table_name where name=:Name and id=:ID';
Nie możesz mieć dwóch where
jest w jednym (pod)zapytaniu