当前位置: 首页
数据库
如何解决Spring Data JPA中的SQL注入问题_利用Query注解的命名参数

如何解决Spring Data JPA中的SQL注入问题_利用Query注解的命名参数

热心网友 时间:2026-04-30
转载

如何解决Spring Data JPA中的SQL注入问题:利用Query注解的命名参数 Query注解里用字符串拼接就是SQL注入温床 在 @Query 注解的 JPQL 或原生 SQL 字符串里,直接用 + 号拼接用户输入,这无异于把数据库的钥匙直接交给了请求参数。虽然 JPQL 不支持将预编译占

如何解决Spring Data JPA中的SQL注入问题:利用Query注解的命名参数

如何解决Spring Data JPA中的SQL注入问题_利用Query注解的命名参数

Query注解里用字符串拼接就是SQL注入温床

@Query 注解的 JPQL 或原生 SQL 字符串里,直接用 + 号拼接用户输入,这无异于把数据库的钥匙直接交给了请求参数。虽然 JPQL 不支持将预编译占位符(比如 ?1)与动态字段名或表名混合使用,但命名参数(:name)本身是安全的——前提是,别用它去拼接 SQL 语句的结构部分。

命名参数只能绑定值,不能绑定列名或表名

这里有个最常见的误区:以为写了 @Query("SELECT * FROM :table WHERE name = :name") 就算用了命名参数。实际上,:table 会被当作一个普通的字面量字符串处理,而不是进行参数替换,运行时要么直接报错,要么查不到任何数据。JPA 规范明确禁止在运行时解析动态的表名或列名。

  • :param 只能出现在 WHERE、HA VING、ORDER BY(值部分)、GROUP BY(值部分)这类**值上下文**中。
  • 表名、列名、函数名、排序方向(ASC/DESC)这些结构部分,必须硬编码在 SQL 里,或者经过外部严格校验后,通过白名单机制进行拼接。
  • 如果业务上确实需要动态表名,建议改用 JdbcTemplate 配合白名单校验和 PreparedStatement,别强行塞进 @Query 里。

安全写法:命名参数 + 严格类型约束 + 白名单兜底

下面这个例子看起来平平无奇,但每一步其实都在为安全加锁:

@Query("SELECT u FROM User u WHERE u.status = :status AND u.name LIKE %:name%")
List findUsers(@Param("status") Integer status, @Param("name") String name);
  • status 参数是 Integer 类型,JPA 底层会自动将其转换为 JDBC 的 setInt() 调用,从根本上杜绝了字符串逃逸的可能。
  • name 参数虽然是 String 类型,但它只用于 LIKE 右侧的模糊匹配,而且通配符 % 是直接写死在 SQL 语句里的,并非从参数中拼接进来。
  • 如果业务要求按多个状态进行筛选,千万别写成 "status IN :statuses"(JPA 不支持直接将数组参数展开到 IN 子句中)。正确的做法是,动态构建 IN 子句,并配合一个经过白名单校验的枚举值列表。

原生 SQL 下命名参数仍安全,但得避开 CONCAT 和字符串函数

当使用 @Query(nativeQuery = true) 切换到原生 SQL 时,命名参数依然会走 JDBC 的预编译机制,安全性有保障。但需要注意的是,某些数据库函数可能会绕过参数化机制,带来隐患:

  • 避免使用 CONCAT(:a, :b):col = :val 这类将参数当作标识符来用的写法。
  • 像 PostgreSQL 的 quote_ident(:table) 函数,看起来能安全处理标识符,但 JPA 本身并不识别这个函数,传进去的仍然是一个未经转义的字符串。
  • 真正需要动态字段时,稳妥的做法是:先用工具类(如 StringUtils.replaceChars(fieldName, ".", "_"))进行基础清洗,再与预设的白名单(例如 Set.of("user_name", "created_at"))进行比对。如果不匹配,直接抛出 IllegalArgumentException 异常。

话说回来,最棘手的问题往往不在于参数怎么写,而在于团队中可能有人在 Service 层偷偷用 String.format 拼接好 SQL,再丢给 JdbcTemplate 去执行。这种代码在编译时不会报错,但只要参数里包含一个单引号或分号,就等于为攻击者敞开了大门。所以,盯紧日志里打印出的最终 SQL 语句,比任何编码规范都更管用。

来源:https://www.php.cn/faq/2328747.html

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
利用AWR报告诊断表空间碎片对扫描性能的影响

利用AWR报告诊断表空间碎片对扫描性能的影响

通过AWR报告中dbfilesequentialread等待异常、物理读请求次数增幅远超读块数、以及SQL执行计划从索引扫描退化为全表扫描这三类信号交叉验证,可判断表空间碎片是否拖慢扫描性能,避免误判。

时间:2026-07-19 10:46
MySQL第三方审计系统只读系统视图权限配置方法

MySQL第三方审计系统只读系统视图权限配置方法

为审计账号配置MySQL只读权限时,performance_schema必须逐表显式授权,不可使用* *或库级批量授权;认证插件必须指定mysql_native_password;无法通过视图封装,必须直接授权原始表。这是审计账号配置的关键注意事项,必须严格遵守,并遵循最小权限原则。

时间:2026-07-19 10:45
Navicat团队项目自定义图标背景色设置方法

Navicat团队项目自定义图标背景色设置方法

Navicat中设置团队项目图标背景色实为两个独立配置:模型图节点颜色需手动修改navicat ini文件并完全重启;SQL编辑器及主窗口背景色通过主题设置。版本一致、配置路径准确、激活ERD模式是效果一致的关键。修改后必须彻底退出程序。

时间:2026-07-19 10:14
SQL嵌套查询中如何有效利用索引覆盖提升性能

SQL嵌套查询中如何有效利用索引覆盖提升性能

SQL嵌套查询中,子查询字段未被索引覆盖会导致全表扫描,而外层EXPLAIN的Usingindex可能误导优化。需为子查询过滤字段建索引,联合索引将SELECT字段包含在内且顺序正确。PostgreSQL可用INCLUDE或组合索引,MySQL8 0+支持函数索引,物化视图需手动建索引并刷新统计信息。

时间:2026-07-19 10:14
SQL窗口函数快速查找用户多设备登录顺序

SQL窗口函数快速查找用户多设备登录顺序

使用ROW_NUMBER()配合PARTITIONBYuser_id和ORDERBYlogin_time,可快速按用户分组并排序登录顺序。漏掉PARTITIONBY会导致全局编号,且必须用ROW_NUMBER()保证编号连续,避免RANK()或DENSE_RANK()的跳号问题。区分首次登录可嵌套MIN()窗口函数。老版本MySQL用变量模拟易出错,建议升级

时间:2026-07-19 10:14
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 热门数据榜