# 和 $ 的区别②

2023-12-15 05:50:55

上节博客说了使用 # 的时候,如果参数为 String ,会自动加上单引号

但是当参数为String 类型的时候,也有不需要加单引号的情况,这时候用 # 那就会出问题

比如根据 升序(asc) 或者?降序(desc) 查找的时候,加了单引号那就会报错

这个时候我们就只能使用 $?

如果看不懂代码,就去看<<Mybatis?的操作(结合上文)续集>>,我这里为了简练一点就不多解释了

@Select("select * from userinfo order by id ${sort}")
    List<UserInfo> selectUserBySort(String sort);
 @Test
    void selectUserBySort() {
        log.info(userInfoMapper.selectUserBySort("asc").toString());
    }

使用 $ 才能正常运行?

还有一种情况不能使用 # ,那就是模糊查询?

进行模糊查询的时候也只能用 $

@Select("select * from userinfo where username like'%${username}%'")
    List<UserInfo> selectUserByLike(String username);
@Test
    void selectUserByLike() {
        log.info(userInfoMapper.selectUserByLike("java").toString());
    }

?有的人可能会觉得那我们在排序和模糊查询的时候使用 $ ,其他有需要引号的情况只要拼接上引号也可以使用 $ ,那我们就不用 # 了吗?

这是不可以滴,因为 $ 存在 SQL 注入的问题

打个比方 :?

select * from userinfo where username = 'admin';

若是此时把admin换成 'or 1='1? ,那就变成了

select * from userinfo where username = ''or 1='1';

(这样前面两个引号就会形成一对,后面两个引号形成一对,这就导致where后面的搜索条件变成username=0或者1=1,因为1=1肯定恒成立,这样运行出来的结果就是搜索到全部数据,这与我们的想法背道而驰)

那这肯定就不对了呀,这就是 SQL 注入

# 就不会存在 SQL 注入的问题

我们用代码进行验证看看,先验证 $

    @Select("select * from userInfo where username = '${username}'")
    List<UserInfo> selectByName(String username);
  @Test
    void selectByName() {
        log.info(userInfoMapper.selectByName("'or 1='1").toString());
    }

?很明显把所有数据都给查出来了,这是错误的

接下来我们试试 #

@Select("select * from userInfo where username = #{username}")
    List<UserInfo> selectByName(String username);
 @Test
    void selectByName() {
        log.info(userInfoMapper.selectByName("'or 1='1").toString());
    }

因为没有名为?'or 1='1 的数据,所以啥也没查出来,没问题

同样是加引号,为什么# 不会发生SQL注入的问题?

SQL 执行的过程为 : 1.语法解析 2.SQL优化 3.SQL编译

然后呢, # 是预编译SQL,将编译一次之后的SQL语句缓存起来了,后面再次执行的时候,省去了解析优化等过程,提高了效率,预编译SQL也可以说是一个模版,往里套数据就行.

比如?select * from userinfo where username = '_____';

预编译SQL就只给你留下了这个位置,你填进去之后就只能是 username 的参数

而即时SQL就是你传的参数是什么就现场进行拼接,拼出来之后再对这条语句进行上面三个过程

所以这就是为什么 # 不会发生 SQL 注入的原因

但是在进行排序的时候,只能使用 $ 的时候,发生SQL注入怎么办呢?

可以进行参数校验,只要不是 asc 和 desc 就不接收这个请求

模糊查询的时候使用Mysql的内置函数

?

@Select("select * from userinfo where username like CONCAT('%',#{username},'%')")
    List<UserInfo> selectUserByLike(String username);
 @Test
    void selectUserByLike() {
        log.info(userInfoMapper.selectUserByLike("java").toString());
    }

?

文章来源:https://blog.csdn.net/qq_40841463/article/details/135007346
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。