三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

springboot项目xml中#{}和${}

springboot项目xml中#{}和${}

两者本质区别

  • ${params.id}:MyBatis 直接字符串替换,把值原样拼进 SQL。相当于字符串拼接。
  • #{params.id}:MyBatis 用 PreparedStatement 预编译占位符 ?,值由驱动单独传参,和 SQL 语句分离。

数字类型在数据库里会被自动转换,所以 #{} 对数字完全适用——数字和字符串都应该用 #{}

为什么 ${} 危险(即使是数字列)

以你原来 where id =${params.id} 为例:

-- 正常:id = 100
delete from sys_app_permission where id =100-- 攻击:id 传 "1 or 1=1"(虽然是 GET 参数,攻击者可以直接拼)
delete from sys_app_permission where id =1 or 1=1      -- 全表删光-- 攻击:id 传 "1; drop table xxx"
delete from sys_app_permission where id =1; drop table xxx

攻击者传的是字符串,不是数字。${} 不知道、也不关心你“本意”是数字,它只负责拼接,所以注入就发生了。

改成 #{} 后:

delete from sys_app_permission where id = ?   -- 参数 '1 or 1=1' 作为整体传给数据库

数据库把 '1 or 1=1' 当成 id 的值去匹配(数字列会转换失败报错,而不是执行注入),注入被彻底堵死

那什么时候必须用 ${}

只有 表名/字段名这类标识符才必须用 ${},因为 #{} 会给标识符加引号变成字符串值,SQL 不合法。

image

 

← 返回列表