Mybatis的Mapper.xml中的SQL引用传递过来参数的方式为:#{parameterName}和${parameterName}。
#{parameterName}
#{parameterName}实现的是向prepareStatement中的预处理中设置参数值,sql语句中的#{}表示一个占位符?,当程序给该位置传入实际的数据内容时,该占位符?会被实际的数据内容替换。
#{parameterName}中的parameterName表示接受输入参数的名称,在使用时不需关心参数值的类型,mybatis会自动进行java类型和jdbc类型之间的映射转换,此外,#{}既可以接收简单数据类型值也可以接收pojo的类型值。
如果#{parameterName}中传输的是简单的数据类型,则parameterName可以设置为value或者其他名称。
select * from user where username= #{username} //#{parameterName}能够有效的解决SQL注入的问题
${parameterName}
${parameterName}是通过${}可以将parameterName传入的内容拼接在Sql语句中且不会进行java类型与jdbc类型之间的映射转换。
如果${parameterName}中传输的是简单的数据类型,则parameterName只能设置为value。
select * from user where username = ${value} //String简单数据类型只能使用value
注:#{}方式取值会先编译后取值,${}会先取值然后编译。
SQL注入攻击,简称SQL攻击或注入攻击,是发生于应用程序之数据库层的安全漏洞。简而言之,是在输入的字符串之中注入SQL指令,在设计不良的程序当中忽略了检查,那么这些注入进去的指令就会被数据库服务器误认为是正常的SQL指令而运行,因此遭到破坏或是入侵。
SQL注入案例:当三哥知道了小舞的用户名而不知道密码,拥有智慧头骨的三哥想到了借助SQL注入来实现免密码登录。
select * from user where username = ${value} and password = ${value} //系统登录时的SQL语句
此时,三哥将username和password值设置为value = " 小舞",password = " '任何值' or 1=1 ",此时就可以成功的登录了。
在次基础上,三哥想到了通过将username和password值设置为value = " '任何值' or 1=1",password = " '任何值' or 1=1 ",来实现对任意系统的登录。
select * from user where (username = '任何值' or 1=1) and (password = '任何值' or 1=1)
该SQL语句实际运行时将变成
select * from user. //实现了免密码登录系统
解决方法:此应用场景下在编写SQL时使用#{}替代${}
注意:使用order by ${index} 而非order by#{index},index为数据表的列索引。因为列索引时int类型数据,而#{index}会将索引值自动转换成字符串。即当index = 1 时,#{index}会自动转换成"1"。