MyBatis中#和$的区别
1. ‘#’ 将传入的数据当成一个字符串,自动加双引号之后显示到sql中;‘$’将传入的数据直接显示到sql中。
实例解释:
- #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by “111”, 如果传入的值是id,则解析成的sql为order by “id”.
- $将传入的数据直接显示生成在sql中。如:order by $user_id $,如果传入的值是111,那么解析成sql时的值为order by user_id, 如果传入的值是id,则解析成的sql为order by id.
2. 排序时使用只能使用 $ ,不能使用 # 。
实例解释:
- 排序使用 # 时, 解析为 order by “id” ,此时 错误语法,无法排序。
- 排序使用 $ 时, 解析为 order by id ,此时 正确语法,可以排序。
3. $ 方式一般用于传入数据库对象,例如传入表名。
4. ‘#’ 可以很大程度防止sql注入(Sql Injection),$ 不能,因此传数据时能用 # 就别用 $。
Sql注入:
SELECT job_id, job_desc, min_lvl, max_lvl
FROM jobs
WHERE (job_id = 1)
假设现在要求我们获取Department表中的所有数据,而且必须保留WHERE语句,那我们只要确保WHERE恒真就OK了,SQL示意代码如下:
SELECT job_id, job_desc, min_lvl, max_lvl
FROM jobs
WHERE (job_id = 1) OR 1 = 1
上面我们使得WHERE恒真,所以该查询中WHERE已经不起作用了,其查询结果等同于以下SQL语句。
SELECT job_id, job_desc, min_lvl, max_lvl
FROM jobs
现在我们把job表中的所有数据都查询出来了,仅仅通过一个简单的恒真表达式就可以进行了一次简单的攻击。 上面就是sql注入了。
模拟:
正常情况:
如果登录用户的用户名是jiayi,密码是123456,在模拟数据库使用 $ 接收参数时,where语句是 where name = jiayi and pwd = 123456 ; 而使用 #接收参数时,where语句是 where name = “jiayi” and pwd = “123456”。
模拟Sql注入
传参数时加 or 1= 1 条件进行Sql注入,此时使用 $ 接收参数时,where语句是 where name = jiayi and pwd = 123456 or 1 = 1,此时 1=1 恒真 ,前面的条件无论对错数据库校验都过了; 但是使用 #接收参数时,数据库语句则是where name = “jiayi” and pwd = “123456 or 1=1”,因此,校验失败,密码错误,#有效的防止了Sql注入。