mybatis中order by和like安全写法:排序字段与方向须用白名单校验(如order by name),模糊查询必须用concat('%', #{keyword}, '%'),禁用'%${keyword}%'。

动态SQL注入无法靠异常捕获或事后过滤解决,必须在SQL构建阶段切断拼接路径——所有${}、字符串拼接、反射式表名列名都属于高危操作。
MyBatis里用${}做排序/模糊查询时怎么写才安全
ORDER BY 和 LIKE 语句里用${}是常见漏洞点,因为#{}不支持动态字段名。但直接拼接用户输入等于开门揖盗。
- 排序字段必须白名单校验:
<choose></choose>+<when test="sortField == 'name'">ORDER BY name</when>,禁止任何自由传入sortField - 模糊查询不能写
LIKE '%${keyword}%',必须用CONCAT('%', #{keyword}, '%'),让数据库函数处理拼接,参数仍走预编译 - 如果排序方向(ASC/DESC)也由前端控制,同样要白名单:
ORDER BY ${sortField} ${sortOrder}→ 改为两个独立白名单字段校验
JdbcTemplate中IN查询和动态表名怎么防注入
JdbcTemplate本身不支持动态长度的IN列表,硬拼?个数或字符串替换都会崩,而表名、列名根本不在参数绑定范围内。
-
IN查询必须换用NamedParameterJdbcTemplate:WHERE id IN (:ids)+MapSqlParameterSource("ids", List.of(1L, 2L)),驱动自动展开问号并绑定 - 表名/列名绝不能来自用户输入:如果真要动态切换表(如分表场景),必须查配置中心或枚举类,再用
switch或Map映射到合法值,禁止任何形式的字符串拼接 - 别信“我只取前10字符”这类弱校验——攻击者可传
user_table/**/UNION/**/SELECT绕过
为什么@WebFilter比@HandlerInterceptor更适合做请求层清洗
@HandlerInterceptor在Spring MVC解析完参数后才介入,此时JSON Body已被读空、文件上传字段已丢失、原始编码已解码,过滤器根本看不到真实攻击载荷。
- 用
@WebFilter(urlPatterns = "/*")+HttpServletRequestWrapper,才能在Servlet容器最前端拿到原始InputStream或getPart() - 必须同时覆盖三种输入源:
getParameter*(表单)、getInputStream()(JSON)、getPart()(multipart),缺一不可 - 正则模式要忽略大小写和编码变形:
(?i)union\s+select|or\s+1=1,但注意别误杀正常业务词(如用户名含order)
真正难防的不是' OR 1=1 --这种明文,而是绕过白名单的编码混淆、多层嵌套注释、或利用框架特性(如MyBatis的<bind></bind>标签)间接拼接——这些必须靠代码审计+SQL日志回溯,没法靠一个过滤器兜底。











