答案是:#{}是预编译处理,${}是字符串替换。
(1)mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值。
(2)mybatis在处理 时 , 就 是 把 {}时,就是把 时,就是把{}替换成变量的值。
(3)使用#{}可以有效的防止SQL注入,提高系统安全性。原因在于:预编译机制。预编译完成之后,SQL的结构已经固定,即便用户输入非法参数,也不会对SQL的结构产生影响,从而避免了潜在的安全风险。
(4)预编译是提前对SQL语句进行预编译,而其后注入的参数将不会再进行SQL编译。我们知道,SQL注入是发生在编译的过程中,因为恶意注入了某些特殊字符,最后被编译成了恶意的执行操作。而预编译机制则可以很好的防止SQL注入
延伸说明一下,预编译机制为什么可以防止SQL注入呢?
要回答这个问题,我们要知道怎么进行的SQL注入,所谓知己知彼,方能百战百胜。
什么是SQL注入??
所谓SQL注入,就是通过把SQL命令插入到Web表单提交或页面请求url的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。
实战举例
有个登陆框如下:
可以看到除了账号密码之外,还有一个公司名的输入框,根据输入框的形式不难推出SQL的写法如下:
SELECT * From table_name WHERE name=‘XX’ and password=‘YY’ and corporate=‘ZZ’
怎么做呢,?
因为没有校验,因此,我们账号密码,都不填写,直接在最后,添加 or 1=1 –
看看与上面SQL组合,成了如下:
SELECT * From table_name WHERE name=’’ and password=’’ and corporate=’’ or 1=1-- ’
从代码可以看出,前一半单引号被闭合,后一半单引号被 “–”给注释掉,中间多了一个永远成立的条件“1=1”,这就造成任何字符都能成功登录的结果。
重要提醒
不要以为在输入框做个检查就够了,不要忘记了,我们web提交表单,是可以模拟url直接访问过去,绕开前段检查。因此,必须是后端,或是数据来检查才能有效防止。
(1)检查用户输入的合法性;
(2)将用户的登录名、密码等数据加密保存。
(3)预处理SQL。
(4)使用存储过程实现查询,虽然不推荐,但也是一个方法。
MySQL预处理是怎么防止的呢?
其实是因为SQL语句在程序运行前已经进行了预编译,在程序运行时第一次操作数据库之前,SQL语句已经被数据库分析,编译和优化,对应的执行计划也会缓存下来并允许数据库已参数化的形式进行查询,当运行时动态地把参数传给PreprareStatement时,即使参数里有敏感字符如 or '1=1’也数据库会作为一个参数一个字段的属性值来处理而不会作为一个SQL指令,如此,就起到了SQL注入的作用了!
具体像这样。例如刚刚那条SQL:
SELECT * From table_name WHERE name=’’ and password=’’ and corporate=’’ or 1=1-’
开启预编译执行SQL的时候,则不会这么处理。会当成一个属性值。什么意思。随便你怎么加,都是一个值。也就是说,如果中间有产生歧义的,都将被处理掉,最后执行相当于是这样:
SELECT * From table_name WHERE name=’’ and password=’’ and corporate="'or 1=1–"
这个大家应该看的懂吧,输入的一串,都被揉在一起,作一个参数,而不是SQL。
这样就无法进行SQL注入了。是不是很巧妙。
转载:http://www.mybatis.cn/archives/70.html
转载:https://blog.youkuaiyun.com/weixin_45179130/article/details/90761966