Sûr
query.SQL.Text := 'select * from table_name where name=:Name';
Ce code est sûr car vous utilisez des paramètres.
Les paramètres sont toujours à l'abri de l'injection SQL.
Non sécurisé
var Username: string;
...
query.SQL.Text := 'select * from table_name where name='+ UserName;
N'est pas sûr car le nom d'utilisateur peut être name; Drop table_name;
Entraînant l'exécution de la requête suivante.
select * from table_name where name=name; Drop table_name;
Également dangereux
var Username: string;
...
query.SQL.Text := 'select * from table_name where name='''+ UserName+'''';
Parce que si le nom d'utilisateur est ' or (1=1); Drop Table_name; --
Il en résultera la requête suivante :
select * from table_name where name='' or (1=1); Drop Table_name; -- '
Mais ce code est sûr
var id: integer;
...
query.SQL.Text := 'select * from table_name where id='+IntToStr(id);
Parce que IntToStr()
n'acceptera que des entiers afin qu'aucun code SQL ne puisse être injecté dans la chaîne de requête de cette façon, uniquement des nombres (ce qui est exactement ce que vous voulez et donc autorisé)
Mais je veux faire des choses qui ne peuvent pas être faites avec des paramètres
Les paramètres ne peuvent être utilisés que pour les valeurs. Ils ne peuvent pas remplacer les noms de champs ou les noms de tables. Donc, si vous souhaitez exécuter cette requête
query:= 'SELECT * FROM :dynamic_table '; {doesn't work}
query:= 'SELECT * FROM '+tableName; {works, but is unsafe}
La première requête échoue car vous ne pouvez pas utiliser de paramètres pour les noms de table ou de champ.
La deuxième requête n'est pas sûre, mais c'est la seule façon d'y parvenir.
Comment rester en sécurité ?
Vous devez vérifier la chaîne tablename
contre une liste de noms approuvés.
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;
...
C'est la seule façon de faire cela, que je connaisse.
BTW Votre code d'origine contient une erreur :
query.SQL.Text := 'select * from table_name where name=:Name where id=:ID';
Devrait être
query.SQL.Text := 'select * from table_name where name=:Name and id=:ID';
Vous ne pouvez pas avoir deux where
est dans une (sous-)requête