Using prepared statements is the best way to prevent SQL injection

sql precompile

definition

SQL precompilation means that the database driver compiles the SQL statement before sending the SQL statement and parameters to the DBMS, so that when the DBMS executes the SQL, it does not need to be recompiled.

Why do you need to precompile

The object PreparedStatement is used in JDBC to abstract the prepared statement and use the precompiled

  1. The precompile phase can optimize the execution of sql.

    The precompiled SQL can be directly executed in most cases, and the DBMS does not need to be compiled again. The more complex the SQL, the more complicated the compilation will be. The precompiled phase can combine multiple operations into one operation.

  2. Prepared statement objects can be reused.

    Cache the PreparedStatement object generated after precompiling a SQL, and use the cached PreparedState object directly for the same SQL next time.

     

Precompilation in Mybatis: Using the #{} syntax, MyBatis will generate a PreparedStatement statement and safely set the PreparedStatement parameter. During this process, MyBatis will perform necessary security checks and escapes.

Example 1:
Execute SQL: Select * from emp where name = #{employeeName}
Parameters: employeeName=>Smith
Executed SQL after parsing: Select * from emp where name = ?
Execute SQL: Select * from emp where name = ${employeeName}
Parameter: employeeName incoming value: Smith
parsed SQL: Select * from emp where name =Smith

 

综上所述、${}方式会引发SQL注入的问题、同时也会影响SQL语句的预编译,所以从安全性和性能的角度出发,能使用#{}的情况下就不要使用${}。

用法 tips

1、能使用 #{ } 的地方就用 #{ }

首先这是为了性能考虑的,相同的预编译 sql 可以重复利用。

其次, ${ } 在预编译之前已经被变量替换了,这会存在 sql 注入问题 。例如,如下的 sql,

select * from ${tableName} where name = #{name} 

假如,我们的参数 tableName 为 user; delete user; -- ,那么 SQL 动态解析阶段之后,预编译之前的 sql 将变为

select * from user; delete user; -- where name = ?;

-- 之后的语句将作为注释,不起作用,因此本来的一条查询语句偷偷的包含了一个删除表数据的 SQL!

2、表名作为变量时,必须使用 ${ }

这是因为,表名是字符串,使用 sql 占位符替换字符串时会带上单引号 '' ,这会导致 sql 语法错误,例如:

select * from #{tableName} where name = #{name};

预编译之后的sql 变为:

select * from ? where name = ?;

假设我们传入的参数为 tableName = "user" , name = "ruhua",那么在占位符进行变量替换后,sql 语句变为

select * from 'user' where name='ruhua';

上述 sql 语句是存在语法错误的,表名不能加单引号 '' (注意,反引号 ``是可以的)。

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326766835&siteId=291194637