被各大技术公众号推送的高级架构师的课程吸引着,说实话失忆馋了
#和$导致有什么区别呢
- 我搜一下mybatis中#和$的区别,发现很多都说#{}可以防止sql注入,但是具体怎么防止,博主没说!实践是检验真理的唯一标准嘛,于是乎,失忆就自测了一把
她说:你可以吗?
失丶忆:试试就能行,争争就能赢。
测试#
- controller
@ApiOperation(value = "测试$和#的区别")
@GetMapping("/getArticleByName")
public Result<ArticleEntity> getArticleByName(@RequestParam("name") String name) {
return Result.success(service.getArticleByName(name));
}
- service层
@Override
public ArticleEntity getArticleByName(String name) {
return this.baseMapper.getArticleByName(name);
}
- dao层
ArticleEntity getArticleByName(@Param("name") String name);
- xml
<select id="getArticleByName" resultMap="BaseResultMap">
SELECT
*
FROM
article
WHERE
title = #{name}
</select>
-
数据库中有两条数据
-
一切都准备好了,现在使用#来自测一把
-
观察一下sql,#是用?占位符,生成sql后再替换?号,这个时候sql已经不会发生改变了
-
可能你会问为什么要这么测,往下看吧
-
还是没有查询到数据,sql注入失败
-
#在我们粗略的测试下坚持了下来,接下来就轮到$了
测试$
<select id="getArticleByName" resultMap="BaseResultMap">
SELECT
*
FROM
article
WHERE
title = ${name}
</select>
- 嗯,老弟,怎么回事,竟然报错了,说好的会防止替换,都能用,但报错是怎么回事。
- 它提示说没有测试这一列, 然后我把测试的内容换成了title
- 结果查询出来了两条
- 失忆这还没有测试sql注入呢,就填写了正常的字符串已经查出来所有了。那测一把sql注入吧
- 结果是全部查出来了
- 通过观察sql可以发现,字符串部分是成功的替换了,但是sql被修改了,这样就有sql注入的问题。
- 因为${}不会给字符串添加引号,所有测试的时候我手动添加了引号
但是$真的就这么差嘛! 肯定不是
- 现在有这样一个场景,我要查询所有文章,要能根据不同的列来排序
- dao层
List<ArticleEntity> listArticle(@Param("column") String column);
- xml
<select id="listArticle" resultMap="BaseResultMap">
SELECT
*
FROM
article
ORDER BY
#{column}
</select>
- 使用#来测试一把
- 数据库中的数据
- 查询出来的数据
- 我们知道order by 模式是按照升序排的,应该查询出来category_id = 1的在前面。与我们预期的不一样。
来测一把$符号
<select id="listArticle" resultMap="BaseResultMap">
SELECT
*
FROM
article
ORDER BY
${column}
</select>
- 只把xml中#替换成了$符号,来看一下结果
- 在我们粗略的测试下,$通过测试,#挂了。
总结
- #可以有效的防止sql注入,它是先用?占一个位置,生成sql后,执行的时候再进行替换,字符串会有" "
- $是直接替换,也不会给字符串添加"", 常用于order by
- 不要盲目了解#{}可以有效的防止sql注入,也要问问自己为什么
- 各有各的使用场景