关于使用#和$的使用
#{}和${}有啥区别:
① 含义不一样:${}是直接替换,#{}是预处理;
② 使用场景不一样:普通的参数用#{},这也是我们日常用的最多的,如果是传递SQL或者SQL关键字,就用${},但需要做好安全验证
③ 安全性问题:#{}不存在安全问题,使用${}也存在安全问题,如SQL注入
SQL注入指应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者在应用程序实现定义好的查询语句的尾上添加额外的SQL语句,执行SQL成功,获取到非法数据
这里写个demo,演示下SQL注入
xml
<select id="getUserById" resultType="org.ongoal.tun.demos.entity.User">
select * from user_info where user_name = '${username}' and password = '${password}'
</select>
apifox入参
控制台打印如下
Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@18576e47] was not registered for synchronization because synchronization is not active JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@440a8ac2] will not be managed by Spring ==> Preparing: select * from user_info where user_name = 'lisi' and password = '' or 1 = '1' ==> Parameters: <== Columns: uid, user_name, password, manager, create_time, update_time <== Row: 3, lisi, 123456, 1, 2024-03-14 17:10:19, 2024-03-14 17:10:24 <== Row: 1753297296487964673, zhangsan, bf6540446c4348b982f65cbdd1cc4522$a22ef612376787d1d3b697c95aa73be6, 0, null, null <== Row: 1753326948434624514, admin, 9bfaf99d54284e78a7de4b5023360ca4$70b4cbc831c70eb4557d5679fcbab939, 1, null, null <== Total: 3 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@18576e47]
由此就获取到了数据库所有的数据,因为最后的1=1成立,类似的还有很多
所以鉴于此,一般情况下,使用#{}去代替${}传参。
下面演示下使用使用${}放SQL关键字
serviceImpl
@Override public List<User> getUserById(String username,String password,Integer sort) { String time = ""; if (1 == sort){ time = "create_time"; } if (2 == sort){ time = "update_time"; } return deviceMapper.getUserById(username,password,time); }
xml
<select id="getUserById" resultType="org.ongoal.tun.demos.entity.User">
select * from user_info where user_name = #{username} and password = #{password} order by ${time} desc
</select>
apifox
控制台
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2468e97c] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4729a351] will not be managed by Spring
==> Preparing: select * from user_info where user_name = ? and password = ? order by update_time desc 此处不是预处理,是已经直接替换
==> Parameters: lisi(String), 123456(String)
<== Columns: uid, user_name, password, age, manager, create_time, update_time
<== Row: 3, lisi, 123456, 17, 1, 2024-03-14 17:10:19, 2024-03-14 17:10:24
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2468e97c]
不用在乎查询的数据是否为一条,主要看的是order by 后面的替换
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)