【Java--SQL】${}与#{}区别和危害
目录
一区别
二SQL${}注入问题
一区别
在MyBatis中,#{}和${}是两种不同的参数占位符,用于在SQL语句中引用变量或参数。它们的区别如下:
1.#{}占位符(预编译):#{}是MyBatis中的预编译占位符,它会把传入的参数值自动进行预编译处理,以防止SQL注入攻击。#{}占位符会将参数值作为一个占位符传递给数据库驱动程序,驱动程序会将其转化为一个预编译的参数并进行安全处理,在执行SQL语句时,会将参数通过参数设置语句传递给数据库。
2.${}占位符(字符串拼接):${}是Mybatis中的字符串拼接占位符,它会直接传入的参数值拼接到SQL语句中。${}占位符会将参数值直接替换到生成的SQL语句中,这种方式比较灵活,可以动态拼接SQL语句的各个部分。
综上所述,#{}占位符提供了更高的安全性,适合用于参数值的传递,而${}占位符具有更高的灵活性的,适合用于动态拼接SQL语句的各个部分,在使用占位符时,应根据具体的需求选择合适的方式,并注意参数值的安全。
简单来说#{}就是预编译处理,${}是字符替换。
预编译处理:是指MyBatis在处理的#{}时,就是把的#{}替换成了?号,使用PreparedStatement的set方法来赋值。也就是说#{}会把{}内的整体看成value,最后再给value加上单引号,重点强调引号内部是一个整体(#{}不会发生SQL注入的根本原因)。
二SQL${}注入问题
xml文件
<mapper namespace="com.caicode.dao.UserDao"><select id="query" resultType="com.caicode.entity.UserEntity">select * from user where sname = '${param1}' and spassword = '${param2}'</select>
</mapper>
测试代码
public static void main(String[] args) throws IOException {UserEntity userEntity = new UserService().queryOne("lisi","' or 1 = '1");System.out.println("登录状态:"+(userEntity == null?"失败":"成功"));}
sql最终的结果
select * from user where sname = 'Lisi' and spassword = '' or 1 = '1'
可以看到把符合结果的数据全部查询出来了,总共11条
而正常来说我们的一般输入是这样的
public static void main(String[] args) throws IOException {UserEntity userEntity = new UserService().queryOne("zhangsan","123qwe");System.out.println("登录状态:"+(userEntity == null?"失败":"成功"));}
这样输入的话,最终的结果是一条。