浅谈Spring与Filter&Interceptor解析过程
字数 2359 2025-08-06 08:35:06
Spring与Filter&Interceptor解析过程详解
0x00 前言
过滤器(Filter)与拦截器(Interceptor)的区别
| 特性 | Filter | Interceptor |
|---|---|---|
| 标准 | JavaEE标准 | Spring框架特有 |
| 依赖 | Servlet容器 | Spring等Web框架 |
| 配置位置 | web.xml或注解 | SpringMVC配置文件或注解 |
| 实现机制 | 函数回调 | AOP应用,Java反射机制 |
| Bean注入 | 不能注入Spring Bean | 可以注入Spring Bean |
| 拦截范围 | 所有请求 | 仅Controller请求和static资源目录下的请求 |
| 执行顺序 | 优先于Interceptor | 在Filter之后执行 |
0x01 过滤器Filter
1.1 Spring中Filter的使用方式
1.1.1 在web.xml配置
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1.1.2 通过@WebFilter注解配置
@WebFilter(urlPatterns = "/*")
public class InvalidRequestFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 处理逻辑
chain.doFilter(request, response);
}
}
启动类添加@ServletComponentScan注解:
@SpringBootApplication
@ServletComponentScan("Filter对应的包路径")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
1.1.3 通过@Bean配置
@Component
public class InvalidRequestFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 处理逻辑
chain.doFilter(request, response);
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public FilterRegistrationBean<InvalidRequestFilter> FilterConfig() {
FilterRegistrationBean<InvalidRequestFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new InvalidRequestFilter());
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
}
1.2 Filter过滤器调用过程分析
- 调用入口:
org.apache.catalina.core.StandardWrapperValve#invoke() - 创建FilterChain:
ApplicationFilterFactory.createFilterChain()- 检查servlet是否为null
- 创建或获取已存在的过滤器链对象
- 获取所有filter的映射对象(filterMaps)
- 匹配逻辑:
- 获取请求的调度类型(dispatcher)和请求路径(requestPath)
- 遍历过滤器映射,根据条件匹配
- 执行流程:
ApplicationFilterChain#doFilterApplicationFilterChain#internalDoFilter- 通过pos索引判断是否执行完所有filter
- 执行完所有filter后执行servlet业务模块
1.2.1 Filter的匹配逻辑
- dispatcher类型:默认为
DispatcherType.REQUEST - requestPath获取:
- 从request的
org.apache.catalina.core.DISPATCHER_REQUEST_PATH属性获取 - 实际来自
mappingData.requestPath - 经过
parsePathParameters()和normalize()处理
- 从request的
- 匹配条件:
- 类型和路径都匹配
- 类型和servlet名称都匹配
- 匹配函数:
matchDispatcher(filterMap, dispatcher)matchFiltersURL(filterMap, requestPath)matchFiltersServlet(filterMap, servletName)
路径匹配规则:
- 完全相等
/*匹配所有/*结尾的前缀匹配*.开头的扩展名匹配
0x02 拦截器Interceptor
2.1 Spring中Interceptor的使用
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 前置处理逻辑
return true;
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/test/**");
}
}
2.2 Interceptor拦截器调用过程分析
- 调用入口:
DispatcherServlet#doDispatch() - 获取HandlerExecutionChain:
RequestMappingHandlerMapping.getHandler()getHandlerInternal()获取handler- 构建
HandlerExecutionChain并添加Interceptor
- 执行流程:
applyPreHandle()执行前置处理- 执行Controller服务
applyPostHandle()执行后置处理triggerAfterCompletion()执行完成处理
2.2.1 Interceptor的匹配逻辑
- 获取请求路径:
ServletRequestPathUtils.getCachedPath() - 匹配模式:
- 默认使用
AntPathMatcher - 高版本可能使用
PathPatternParser
- 默认使用
- 匹配过程:
- 检查
excludePatterns和includePatterns - 根据路径类型调用不同匹配器
- 对路径进行规范化处理
- 检查
0x03 潜在的安全问题
3.1 解析差异导致的Filter失效
问题原因:
- Spring高版本使用
PathPattern进行路径匹配 - Filter基于Servlet的匹配逻辑
- 两者解析规则存在差异
示例场景:
@RestController
@RequestMapping("/admin")
public class AdminController {
@RequestMapping(value = "/page", method = RequestMethod.GET)
public String page() {
return "admin page";
}
}
Filter配置:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public FilterRegistrationBean<InvalidRequestFilter> FilterConfig() {
FilterRegistrationBean<InvalidRequestFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new InvalidRequestFilter());
registrationBean.addUrlPatterns("/admin/*");
return registrationBean;
}
}
绕过方式:
/admin/../page;可能绕过Filter检查- 因为Tomcat会规范化路径,而Spring可能不会
解决方案:
- 使用Spring Security的
HTTP Firewall Filter - 避免自行实现安全相关的Filter
0x04 最佳实践
-
路径匹配:
- 了解Filter和Interceptor的不同匹配规则
- 注意Tomcat和Spring的路径解析差异
-
安全防护:
- 优先使用成熟安全框架(如Spring Security)
- 避免在Filter中实现关键安全逻辑
-
性能考虑:
- Filter适用于全局性、与业务无关的处理
- Interceptor适用于与业务相关的处理
-
版本兼容:
- 注意Spring版本升级带来的路径匹配变化
- 测试不同路径模式下的行为一致性