Sikker
query.SQL.Text := 'select * from table_name where name=:Name';
Denne kode er sikker, fordi du bruger parametre.
Parametre er altid sikre mod SQL-injektion.
Usikker
var Username: string;
...
query.SQL.Text := 'select * from table_name where name='+ UserName;
Er usikker, fordi brugernavn kunne være name; Drop table_name;
Det resulterer i, at følgende forespørgsel udføres.
select * from table_name where name=name; Drop table_name;
Også Usikker
var Username: string;
...
query.SQL.Text := 'select * from table_name where name='''+ UserName+'''';
Fordi det hvis brugernavn er ' or (1=1); Drop Table_name; --
Det vil resultere i følgende forespørgsel:
select * from table_name where name='' or (1=1); Drop Table_name; -- '
Men denne kode er sikker
var id: integer;
...
query.SQL.Text := 'select * from table_name where id='+IntToStr(id);
Fordi IntToStr()
vil kun acceptere heltal, så ingen SQL-kode kan injiceres i forespørgselsstrengen på denne måde, kun tal (hvilket er præcis, hvad du ønsker og dermed tilladt)
Men jeg vil gerne gøre ting, der ikke kan gøres med parametre
Parametre kan kun bruges til værdier. De kan ikke erstatte feltnavne eller tabelnavne. Så hvis du vil udføre denne forespørgsel
query:= 'SELECT * FROM :dynamic_table '; {doesn't work}
query:= 'SELECT * FROM '+tableName; {works, but is unsafe}
Den første forespørgsel mislykkes, fordi du ikke kan bruge parametre til tabel- eller feltnavne.
Den anden forespørgsel er usikker, men er den eneste måde, dette kan gøres på.
Hvordan forbliver du sikker?
Du skal tjekke strengen tablename
mod en liste over godkendte navne.
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;
...
Det er den eneste måde at gøre dette på, som jeg kender til.
BTW Din originale kode har en fejl:
query.SQL.Text := 'select * from table_name where name=:Name where id=:ID';
Bør være
query.SQL.Text := 'select * from table_name where name=:Name and id=:ID';
Du kan ikke have to where
er i én (under)forespørgsel