安全
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;
...
据我所知,这是唯一的方法。
顺便说一句,您的原始代码有错误:
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