Mybatis的#{}与${}占位符
所有SQL语句在被执行之前,必须编译,在编译之前,必须经过词法分析、语义分析!
Mybatis中的#{}格式的占位符是预编译的,即SQL语句会先经过词法分析、语义分析,再编译,当编译完成后,再将值代入到编译结果中一并执行!由于是预编译的,此前已经完成语义分析,语义是已经确定的,占位符的位置一直是某个值,不可能是字段名,所以,所有值都不需要使用单引号框住!并且,由于是预编译的,所以不存在SQL注入的问题!使用这种占位符时,占位符位置只能表示某个值!
Mybatis中的${}格式的占位符不是预编译的,即先将值代入到SQL语句中,然后,并代入后的结果再执行词法分析、语义分析、编译,最终执行!由于不是预编译的,而是先将值代入到SQL语句中,对于非数值、非布尔值的其它值而言,如果不加单引号,就会被误以为是字段名,所以,所有非数值、非布尔值的其它值都必须使用一对单引号框住!并且,由于不是预编译的,向SQL语句中传入的值有可能改变SQL的语义,是存在SQL注入风险的!使用这种占位符时,占位符位置可以表示SQL语句的任何片段!
SQL注入代码示例:
root 123456
select * from user where username='root' and password='123456';
root 1' or 'x'='x
select * from user where username='root' and password='1' or 'x'='x';