最近在测试mybatis的${}传参时的sql注入问题时,遇到了这个bug,记录一下,本人感到非常奇怪。
具体报错:
Exception in thread “main” org.apache.ibatis.exceptions.PersistenceException:
Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column ‘root’ in ‘where clause’
The error may exist in com/jia/dao/UserMapper.xml
The error may involve com.jia.dao.UserMapper.getUserByName-Inline
The error occurred while setting parameters
SQL: select * from user where username=root
具体编写的代码
持久层接口相应的xml文件 select语句
<select id="getUserByName" parameterType="java.lang.String" resultType="com.jia.pojo.User">
select * from user where username=${username}
</select>
测试类中调用接口的相关代码
User user = mapper.getUserByName("五王");
System.out.println(user);
这里使用${}传参的写法(而没有使用#{}传参)主要是测试其sql注入问题。但是就是这么简单的代码报了上面列出的错误。
分析
仔细查看一下报错提示,提示我未知的列 ’root‘,很纳闷自己并没有传入’root‘字符串,但是最终预编译出来的sql语句却是
select * from user where username=root
于是我开始从xml文件中编写的select语句找原因,最开始猜想的是编写的sql语句空格的问题,果然我把${username}改成${ username} 就多了一个空格,最终问题得到了解决,预编译中的sql中出现了传入的参数
SQL: select * from user where username=五王
另外提一下,我上面写的的${username}并不正确,正确写法应当是’${username}’,这个就涉及到${}和#{}的区别了,大家可以找相应的文章深入了解
更新一下,后来查看了一下原来那个root是从数据源的配置文件中读取的数据库的username值,真是离谱。这样的话,传参的时候(${username})可以考虑换一个名字,这样的话就不会出现上面的空格问题了