目录
- [1. 什么是 Filter?](#1. 什么是 Filter?)
- [2. Filter 的作用](#2. Filter 的作用)
-
- [2.1 身份认证](#2.1 身份认证)
- [2.2 权限校验](#2.2 权限校验)
- [2.3 请求日志](#2.3 请求日志)
- [2.4 全局 Header 处理](#2.4 全局 Header 处理)
- [2.5 防跨域 CORS](#2.5 防跨域 CORS)
- [2.6 安全防护](#2.6 安全防护)
- [3. Filter 基本使用](#3. Filter 基本使用)
- [4. Filter 的注册方式](#4. Filter 的注册方式)
-
- [4.1 @Component 注册](#4.1 @Component 注册)
- [4.2 FilterRegistrationBean 注册](#4.2 FilterRegistrationBean 注册)
- [4.3 Spring Security 注册排序 Filter](#4.3 Spring Security 注册排序 Filter)
- [5. OncePerRequestFilter 是什么?](#5. OncePerRequestFilter 是什么?)
-
- [5.1 防止重复执行](#5.1 防止重复执行)
- [5.2 提供 shouldNotFilter()](#5.2 提供 shouldNotFilter())
- [6. 多个 Filter 如何执行?](#6. 多个 Filter 如何执行?)
- [7. Filter 顺序如何指定?](#7. Filter 顺序如何指定?)
-
- [7.1 @Order](#7.1 @Order)
- [7.2 FilterRegistrationBean](#7.2 FilterRegistrationBean)
- [7.3 Spring Security Filter](#7.3 Spring Security Filter)
- [8. Spring Security Filter Chain](#8. Spring Security Filter Chain)
- [9.注意:不要把同一个 Filter 注册两次](#9.注意:不要把同一个 Filter 注册两次)
- [10. Filter、Interceptor、AOP 区别](#10. Filter、Interceptor、AOP 区别)
-
- [10.1 执行位置不同](#10.1 执行位置不同)
- [10.2 对比表](#10.2 对比表)
- [11. 什么场景适合 Filter?](#11. 什么场景适合 Filter?)
-
- [11.1 JWT认证](#11.1 JWT认证)
- [11.2 网关安全](#11.2 网关安全)
- [11.3 全局处理](#11.3 全局处理)
- [12. 什么情况更适合 Interceptor?](#12. 什么情况更适合 Interceptor?)
- [13. Filter 与 Interceptor 实际组合](#13. Filter 与 Interceptor 实际组合)
- [14. 完整示例:三个 Filter 按顺序执行](#14. 完整示例:三个 Filter 按顺序执行)
-
- [第一个 Filter](#第一个 Filter)
- [第二个 Filter](#第二个 Filter)
- [第三个 Filter](#第三个 Filter)
- [15. Filter 核心知识总结图](#15. Filter 核心知识总结图)
- [16. 一句话总结](#16. 一句话总结)
1. 什么是 Filter?
在 Java Web 开发中,Filter(过滤器)是 Servlet 规范提供的一种请求拦截机制。
它可以在:
- 请求进入 Controller 之前
- 响应返回客户端之前
对 HTTP 请求和响应进行统一处理。
简单理解:
Filter 就像 Web 请求进入系统前的一道"门卫",所有请求必须经过它检查,然后决定是否继续向后执行。
一个 HTTP 请求完整流程:
客户端请求
↓
Filter
↓
DispatcherServlet
↓
Controller
↓
Service
↓
数据库
↓
响应返回
↓
Filter
↓
客户端
2. Filter 的作用
Filter 最常见用途:
2.1 身份认证
例如:
- JWT Token 校验
- 登录状态检查
- 用户身份解析
示例:
java
String token = request.getHeader("Authorization");
if(token == null){
response.setStatus(401);
return;
}
2.2 权限校验
例如:
用户访问:
/admin/user/delete
Filter 判断:
当前用户
|
|
是否拥有删除权限?
没有权限:
403 Forbidden
2.3 请求日志
统一记录:
- 请求 URL
- 请求参数
- 用户信息
- 请求耗时
例如:
request start
/api/order/query
cost 120ms
2.4 全局 Header 处理
例如:
统一添加:
X-Request-ID
Trace-ID
方便链路追踪。
2.5 防跨域 CORS
例如:
处理:
Access-Control-Allow-Origin
2.6 安全防护
例如:
- XSS 防护
- SQL 注入检测
- Response Header 安全设置
3. Filter 基本使用
Servlet 原生 Filter:
java
public class MyFilter implements Filter {
@Override
public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("请求进入 Filter");
//继续执行后面的 Filter
chain.doFilter(request,response);
System.out.println("响应离开 Filter");
}
}
重点:
java
chain.doFilter(request,response);
表示:
当前 Filter 处理完成,继续执行后续流程。
如果不调用:
java
chain.doFilter()
请求会直接结束。
例如:
java
if(token非法){
response.setStatus(401);
return;
}
流程:
Request
↓
AuthenticationFilter
↓
Token失败
↓
返回401
↓
Controller不会执行
4. Filter 的注册方式
定义 Filter 并不会自动生效。
必须注册。
常见有三种方式。
4.1 @Component 注册
java
@Component
public class LoginFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain)throws IOException, ServletException {
System.out.println("Login Filter");
filterChain.doFilter(request,response);
}
}
Spring Boot 启动:
扫描 Bean
↓
发现 Filter
↓
注册到 Servlet Filter Chain
缺点:
默认所有请求都会经过。
4.2 FilterRegistrationBean 注册
更加灵活。
java
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<LoginFilter> loginFilter(){
FilterRegistrationBean<LoginFilter> bean =
new FilterRegistrationBean<>();
bean.setFilter(new LoginFilter());
//过滤路径
bean.addUrlPatterns("/api/*");
//执行顺序
bean.setOrder(1);
return bean;
}
}
效果:
/api/*
↓
LoginFilter
/static/*
↓
不经过
4.3 Spring Security 注册排序 Filter
Spring Security 一般不要靠:
java
@Order
排列 Security Filter。
而应该:
java
addFilterBefore
java
addFilterAfter
java
addFilterAt
例如:
java
//注册 jwtFilter 放到 UsernamePasswordAuthenticationFilter 前,也就是 jwtFilter 先执行
http.addFilterBefore(
jwtFilter,
UsernamePasswordAuthenticationFilter.class
);
意思:
tex
JwtFilter
↓
UsernamePasswordAuthenticationFilter
或者:
java
//注册 logFilter 放到 AuthenticationFilter 后,也就是 AuthenticationFilter 先执行
http.addFilterAfter(
logFilter,
AuthenticationFilter.class
);
意思:
tex
AuthenticationFilter
↓
LogFilter
完整示例,在企业项目中,认证相关 Filter 最常见方式:
加入 Spring Security Filter Chain。
例如:
java
@Configuration
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http, JwtFilter jwtFilter) throws Exception {
http.addFilterBefore(
jwtFilter,
UsernamePasswordAuthenticationFilter.class
);
return http.build();
}
}
执行:
JwtFilter
↓
UsernamePasswordAuthenticationFilter
常用于:
- JWT
- OAuth2
- 内部接口认证
- 签名验证
5. OncePerRequestFilter 是什么?
Spring 提供:
OncePerRequestFilter
用于解决:
一个请求只执行一次 Filter。
例如:
你有 LoginFilter 和 JwtAuthenticationFilter ,它们都 继承 OncePerRequestFilter:
java
@Component
public class LoginFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain)throws ServletException, IOException {
System.out.println("LoginFilter");
filterChain.doFilter(request,response);
}
}
@Slf4j
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal( HttpServletRequest request,HttpServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
log.info("JWT认证");
filterChain.doFilter(request,response);
}
}
如果两个 Filter 都注册成功:
tex
Spring Security Filter Chain
|
↓
LoginFilter 执行一次
↓
JwtAuthenticationFilter 执行一次
↓
Controller
OncePerRequestFilter 的"一次"是什么意思?
它不是:
错误理解:一个请求只能执行一个 OncePerRequestFilter
而是:
正确理解:同一个 OncePerRequestFilter 实例,对于同一次 HTTP 请求,只执行一次。
继承关系:
Filter
↓
GenericFilterBean
↓
OncePerRequestFilter
↓
自己的Filter
通常 Spring Boot 项目不会直接实现:
java
Filter
而是:
java
extends OncePerRequestFilter
优势:
5.1 防止重复执行
某些情况下:
- forward
- include
- error dispatch
可能导致 Filter 多次执行。
OncePerRequestFilter 会保证:
一次HTTP请求
↓
Filter只执行一次
5.2 提供 shouldNotFilter()
例如:
只过滤:
/api/*
@Override
protected boolean shouldNotFilter(
HttpServletRequest request){
return !request
.getRequestURI()
.startsWith("/api");
}
6. 多个 Filter 如何执行?
实际项目中通常有多个 Filter:
例如:
TraceIdFilter
↓
CorsFilter
↓
AuthenticationFilter
↓
AuthorizationFilter
↓
ResponseFilter
↓
Controller
Filter 是一个链:
Filter1
↓
Filter2
↓
Filter3
↓
Controller
↓
Filter3
↓
Filter2
↓
Filter1
类似:
洋葱模型
7. Filter 顺序如何指定?
7.1 @Order
java
@Component
@Order(1)
public class LogFilter extends OncePerRequestFilter {
}
@Component
@Order(2)
public class AuthFilter extends OncePerRequestFilter {
}
执行:
LogFilter
↓
AuthFilter
↓
Controller
规则:
数字越小,优先级越高
7.2 FilterRegistrationBean
java
bean.setOrder(1);
7.3 Spring Security Filter
推荐:
java
addFilterBefore()
addFilterAfter()
addFilterAt()
例如:
java
http.addFilterBefore(
jwtFilter,
UsernamePasswordAuthenticationFilter.class
);
表示:
jwtFilter
↓
UsernamePasswordAuthenticationFilter
8. Spring Security Filter Chain
Spring Security 本身也是通过 Filter 实现。
整体:
HTTP Request
↓
DelegatingFilterProxy
↓
FilterChainProxy
↓
Spring Security Filters
↓
DispatcherServlet
↓
Controller
例如:
SecurityContextFilter
↓
JwtAuthenticationFilter
↓
AuthorizationFilter
↓
Controller
9.注意:不要把同一个 Filter 注册两次
这是项目里很常见的坑。
假设:
java
@Component
public class AuthenticationFilter
extends OncePerRequestFilter {
}
然后又:
java
http.addFilterBefore(
authenticationFilter,
UsernamePasswordAuthenticationFilter.class
);
有可能造成这个 Filter:
tex
既作为 Servlet Filter 注册
又进入 Spring Security Filter Chain
从设计上就重复了。
虽然:
java
OncePerRequestFilter
有"一次请求一次执行"的保护机制,但依然不建议这么做。
Security Filter 通常推荐:
java
@Bean
public AuthenticationFilter authenticationFilter() {
return new AuthenticationFilter(...);
}
然后:
java
http.addFilterBefore(...)
而不是同时:
java
@Component
和
java
addFilterBefore()
10. Filter、Interceptor、AOP 区别
这是 Java Web 中非常经典的问题。
10.1 执行位置不同
HTTP请求
↓
Filter
↓
DispatcherServlet
↓
Interceptor
↓
Controller
↓
AOP
↓
Service
10.2 对比表
| 对比 | Filter | Interceptor | AOP |
|---|---|---|---|
| 所属规范 | Servlet | Spring MVC | Spring |
| 作用范围 | HTTP请求 | Controller方法 | Java方法 |
| 能否获取请求 | 可以 | 可以 | 通常不直接 |
| 能否获取Controller信息 | 不方便 | 可以 | 不可以 |
| 执行位置 | 最前面 | Controller之前 | 方法调用 |
| 典型用途 | 认证、安全、日志 | 权限、参数校验 | 事务、日志 |
| 技术 | 所在层级 | 能处理什么 |
|---|---|---|
| Filter | Servlet 层 | HTTP 请求 |
| Interceptor | Spring MVC 层 | Controller 请求 |
| AOP | Spring Bean 层 | 方法调用 |
11. 什么场景适合 Filter?
适合:
11.1 JWT认证
请求
↓
解析Token
↓
设置用户信息
↓
Controller
11.2 网关安全
例如:
- API签名
- 时间戳校验
- 防重放攻击
11.3 全局处理
例如:
- TraceId
- 日志
- CORS
- Header
12. 什么情况更适合 Interceptor?
Interceptor 更了解 Spring MVC。
例如:
Controller:
java
@GetMapping("/order")
@Permission("ORDER_QUERY")
public Order query(){
}
Interceptor 可以:
java
HandlerMethod method
获取:
java
@Permission
然后判断权限。
所以:
适合:
- Controller权限
- 注解鉴权
- 登录用户操作限制
13. Filter 与 Interceptor 实际组合
企业项目通常:
Filter 负责:用户是谁?Token是否合法?
↓
Interceptor 负责:用户有没有权限访问这个接口?
↓
Controller
↓
Service
↓
AOP 负责:事务、日志
14. 完整示例:三个 Filter 按顺序执行
第一个 Filter
java
@Component
@Order(1)
public class LogFilter extends OncePerRequestFilter {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain chain)throws IOException, ServletException {
System.out.println("Log before");
chain.doFilter(request,response);
System.out.println("Log after");
}
}
第二个 Filter
java
@Component
@Order(2)
public class AuthenticationFilter extends OncePerRequestFilter {
protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response,
FilterChain chain)throws IOException, ServletException {
System.out.println("Auth before");
chain.doFilter(request,response);
System.out.println("Auth after");
}
}
第三个 Filter
java
@Component
@Order(3)
public class TraceFilterextends OncePerRequestFilter {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("Trace before");
chain.doFilter(request,response);
System.out.println("Trace after");
}
}
Controller:
java
@GetMapping("/test")
public String test(){
System.out.println("Controller");
return "success";
}
执行结果:
Log before
Auth before
Trace before
Controller
Trace after
Auth after
Log after
原因:
Filter 是嵌套调用模型:
Log
Auth
Trace
Controller
Trace
Auth
Log
15. Filter 核心知识总结图
HTTP Request
|
↓
+----------------+
| Filter |
+----------------+
|
+----------------------+----------------+
| | |
↓ ↓ ↓
Authentication Log/Trace Security
JWT Token RequestId CORS
权限验证 请求日志 Header处理
|
↓
DispatcherServlet
|
↓
Interceptor
|
↓
Controller
|
↓
AOP
|
↓
Service
16. 一句话总结
Filter 是 Servlet 层面的请求拦截器,负责处理进入系统的 HTTP 请求;
Spring Boot 中通常通过
@Component、FilterRegistrationBean或 Spring Security 的addFilterBefore/addFilterAfter注册;企业项目中认证、安全类逻辑优先使用 Filter,而 Controller 级别的权限控制更适合使用 Interceptor,业务方法增强则使用 AOP。