@Aspect不适合统一拦截SQL注入,因其执行时机过晚,仅作用于方法调用层,无法获取原始请求参数、JSON Body、Header等,而Filter可在Servlet入口统一处理所有输入源。

@Aspect 不适合统一拦截 SQL 注入请求——它根本拦不到真正的攻击入口。
Spring Boot 中的切面(@Aspect)在方法调用时才生效,比如进入 @Service 或 @Repository 方法那一刻。但此时用户输入早已被解析、转换、甚至拼进 SQL 字符串里了。如果 DAO 层用了 ${}、String.format() 或手动字符串拼接,@Aspect 看到的只是“已经污染过的参数”,既无法还原原始请求,也无法阻止语句执行。
为什么 @Aspect 拦不住 SQL 注入
- 它不接触原始 HTTP 请求体(
getInputStream())、查询参数(getParameterMap())、Header 或 Path Variable - 对 JSON Body、multipart/form-data、文件上传字段完全无感知
- 无法覆盖 Spring Security 认证前的未授权请求(
@Aspect依赖 Spring 上下文,可能晚于 Filter 链) - 即使你写了个
@Before("execution(<em> com.example..</em>Controller.*(..))"),拿到的也只是反序列化后的对象,不是原始字符串
真正该用 Filter,而不是 @Aspect
Filter 在 Servlet 容器最外层运行,能拿到未经处理的原始请求数据:
-
request.getParameterNames()和getParameterMap()(GET/POST 表单) -
request.getInputStream()(JSON、XML、纯文本) -
request.getReader()(兼容字符编码) -
request.getParts()(文件上传中的表单字段)
关键是要包装 HttpServletRequestWrapper,重写读取逻辑,对所有字符串值做统一清洗或校验。
示例要点:
- 使用
@WebFilter(urlPatterns = "/*")注册,确保覆盖全部入口 - 加
@Component,否则嵌入式容器(Tomcat/Jetty)不会加载 - 若集成 Spring Security,SQL 过滤器必须排在
SecurityFilterChain之前 - 排除路径如
/actuator/health、/swagger-ui.html、/css/,避免误杀
Filter 里怎么判断和处理可疑内容
别只靠正则匹配 "select|union|drop" —— 用户昵称叫 "User_Select" 就会被拦,误杀率高。
推荐组合策略:
- 对所有字符串型参数(包括 JSON 解析后的字段值),先
trim()+ 判空 - 白名单优先:ID 字段只允许
\d+,邮箱走标准正则,手机号用运营商号段校验 - 对无法白名单的字段(如搜索关键词),用
StringEscapeUtils.escapeSql()(Apache Commons Text 1.10+)转义单引号、分号、--、/*等,但仅作辅助,不能替代预编译 - 检测到高危模式时,直接
response.sendError(400)中断,不进后续流程 - 日志中禁止打印原始参数值(尤其
request.getParameterMap()全量 dump),防止脱敏失效后泄露 payload
真正难的不是写一个能“匹配几个关键字”的切面,而是确认它在 JSON Body、文件上传、带编码的 URL 参数、不同 Content-Type 下都稳定生效。而 @Aspect 从设计上就做不到这点——它连原始请求流都碰不到。


















