发表于: 2020-06-04 22:23:09

1 1534


今天完成的事情:

1. 写完了 controller 并且测试过没有问题


遇到的问题:

1. sql 注入

解决的办法:

 mapper.xml 文件中使用 #{} 的方式接受参数即可。


收获:

1.  ${paramname} #{paramname}

有一次日报提了 mybatis @Param 注解,当时说在不使用这个注解的情况下,xml 中引用参数的方式有且只有一种:#{paramname}(参数名任意写)

经过我的实验,可以确定这句话是完全错误的!

 

无论如何,${paramname} #{paramname} 相互替换后并不会影响使用!

那么这两个符号的区别到底在哪里?

以我现在做的搜索为例:

<selectid="search"parameterType="java.lang.String"resultMap="BaseResultMap">

select

id,name,introduction

fromgallery

whereconcat(`name`,`introduction`)

likeconcat('%',#{keyword,jdbcType=VARCHAR},'%')

</select>

 

  1. a,使用 #{keyword,jdbcType=VARCHAR}      这样的形式接受参数

log信息如下:

  1. b,使用 ${keyword,jdbcType=VARCHAR}      这样的形式接受参数

log信息如下:

并且接下来是这样的报错:

postman也会收到一个错误的返回信息:

 

原因:

log 信息打印出来的 sql 语句可以看出来,在 mapper.xml 中使用 #{} 的方式传参的话 sql 语句会被预编译,内部填入的所有字符都会被当作字符串对待不会被mysql 再次编译,也就不存在 sql 注入的问题。

使用 ${} 的方式传参的话,mybatis 是在接受到参数后再去拼接 sql,如果恰好需要填入用户输入的信息,那么一定要注意防止 sql 注入

这才是这两个符号的本质区别!

 

那么为什么要有两种符号呢?又分别适合在哪些环境下使用?

场景:多条件查询/任意字段排序

也就是说我们需要使用的查询方式特别的灵活,有时候只需要查询一个字段,但是有时候是两个甚至更多字段需要查询。

又或者我们需要使用 id 字段顺序排序,但可能又会用到 name 字段逆序排序。

这个时候我们为了少写重复的语句常常需要在接收到参数后再去拼接 sql,那么我们就需要使用到 ${} 这个符号在 xml 文件中传参了。

 

场景:用户搜索

这个时候往往是用户给我们一个关键词,然后我们拿去 like 查询,当然我么也可以使用 ${} 的方式传参,但是强烈不建议这么做!原因就是防 sql 注入!

当然防 sql 注入也不止一种方式,正则替换、设置拦截器等等很多种方式都可以起到一定的效果,但是我们也可以使用 #{} 传参的方式预编译好 sql 语句就可以挡住所有的 sql 注入。

 

在查询资料的过程中遇到了一种说法,说 #{} 的方式传参是被双引号包裹的,${} 传参是被单引号包裹的,所以会被 sql 注入··· 光明正大的胡说八道··· 我当时都信了,要不是自己动手试了一下还真就被蒙过去了。


明天的计划:

1. 部署 nginx 动静分离并且测试




返回列表 返回列表
评论

    分享到