🤟致敬读者
- 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉
📘博主相关
文章目录
📃文章前言
- 🔷文章均为学习工作中整理的笔记。
- 🔶如有错误请指正,共同学习进步。
Spring Security 中的过滤器(Filter
)和拦截器(HandlerInterceptor
)
理解 Spring Security 中的过滤器(Filter
)和拦截器(HandlerInterceptor
)对于面试和实际应用都至关重要。它们在请求处理流程中扮演着不同但有时又协同的角色。下面进行详细解析:
核心概念区分
过滤器 (
javax.servlet.Filter
):- 归属: Servlet 规范 (J2EE) 定义的标准组件。不依赖于任何特定框架(如 Spring)。
- 作用范围: 作用于 Servlet 容器级别。任何进入 Servlet 容器(如 Tomcat, Jetty)的请求和离开容器的响应都会经过配置的过滤器链。
- 职责:
- 在请求到达
Servlet
(通常是 Spring MVC 的DispatcherServlet
) 之前执行预处理逻辑。 - 在响应离开
Servlet
之后执行后处理逻辑。 - 可以修改请求 (
HttpServletRequest
) 和修改响应 (HttpServletResponse
)。 - 可以中断请求处理链(例如,直接返回响应、重定向)。
- 在请求到达
- 生命周期: 由 Servlet 容器管理。
- 访问信息: 主要访问
ServletRequest
和ServletResponse
。它们对 Spring 的上下文(如ApplicationContext
, beans)没有直接访问权限(除非通过特殊手段如SpringBeanAutowiringSupport
,但一般不推荐在 Filter 中直接注入 Bean)。
拦截器 (
org.springframework.web.servlet.HandlerInterceptor
):- 归属: Spring MVC 框架定义的组件。
- 作用范围: 作用于 Spring MVC 的 DispatcherServlet 内部。只有被
DispatcherServlet
路由的请求(即映射到@Controller
的请求)才会经过配置的拦截器链。 - 职责:
- 在 Controller 方法执行之前 (
preHandle
) 执行预处理逻辑。 - 在 Controller 方法执行之后、视图渲染之前 (
postHandle
) 执行后处理逻辑(如果 Controller 方法成功执行)。 - 在 整个请求完成之后(视图渲染之后或发生异常之后)(
afterCompletion
) 执行清理逻辑(无论 Controller 方法是否成功执行)。 - 可以访问 HandlerMethod (即将要执行的 Controller 方法对象) 和 ModelAndView (在
postHandle
中)。 - 可以中断 Controller 方法的执行(在
preHandle
中返回false
)。
- 在 Controller 方法执行之前 (
- 生命周期: 由 Spring 的
ApplicationContext
管理。因此,可以方便地使用依赖注入(@Autowired
,@Resource
等)获取其他 Spring Bean。 - 访问信息: 可以访问 Spring MVC 的特定对象,如
HandlerMethod
,ModelAndView
。
执行顺序图示
理解它们在请求处理管道中的位置是关键:
HTTP Request
↓
Servlet Container (Tomcat, Jetty, etc.)
↓
---> [Filter 1] ---> [Filter 2] ---> ... ---> [Filter N] ---> (Spring Security's FilterChainProxy is usually here!)
↓
DispatcherServlet (Spring MVC Entry Point)
↓
---> [Interceptor 1.preHandle]
↓
---> [Interceptor 2.preHandle]
↓
... (All Interceptors' preHandle called in order)
↓
---> HandlerAdapter (Actually invokes the Controller method)
↓
---> [Interceptor 2.postHandle] <--- (Reverse order!)
↓
---> [Interceptor 1.postHandle] <---
↓
View Rendering (if applicable)
↓
---> [Interceptor 2.afterCompletion] <--- (Reverse order! Called regardless of success/exception)
↓
---> [Interceptor 1.afterCompletion] <---
↓
DispatcherServlet
↓
<--- [Filter N] <--- ... <--- [Filter 2] <--- [Filter 1] <--- (Response processing)
↓
HTTP Response
- 关键点 1: 所有过滤器 (
Filter
) 都在DispatcherServlet
之前执行。 这意味着 Spring Security 的核心安全逻辑(认证、授权、CSRF 保护等)必须作为过滤器来实现,因为它们需要在请求进入 Spring MVC 的核心处理流程(包括 Controller 和 Interceptor)之前完成安全检查。 - 关键点 2: 拦截器 (
HandlerInterceptor
) 在DispatcherServlet
内部,Controller 方法执行前后执行。 它们工作在 Spring MVC 的上下文中,可以感知 Controller 方法级别的信息。
Spring Security 如何利用过滤器
FilterChainProxy
: 这是 Spring Security 的核心入口。它本身就是一个特殊的Filter
(通常注册在 Servlet 容器过滤器链中一个靠前的位置,比如/*
)。它的工作是管理和协调 Spring Security 内部定义的一系列安全过滤器 (SecurityFilterChain
)。SecurityFilterChain
: 包含一组有序的、特定于 Spring Security 的Filter
实现。每个SecurityFilterChain
可以匹配不同的请求模式(如/api/**
,/admin/**
)。- 典型的安全过滤器:
SecurityContextPersistenceFilter
: 在请求开始时从SecurityContextRepository
(默认是HttpSessionSecurityContextRepository
) 加载SecurityContext
(包含认证信息),在请求结束时保存它(如果需要)。UsernamePasswordAuthenticationFilter
: 处理基于表单的登录 (POST /login
)。BasicAuthenticationFilter
: 处理 HTTP Basic 认证。BearerTokenAuthenticationFilter
: 处理 OAuth2 Bearer Token 认证 (JWT 等)。AnonymousAuthenticationFilter
: 如果请求还没有认证信息,创建一个AnonymousAuthenticationToken
代表匿名用户。SessionManagementFilter
: 处理会话固定保护、并发会话控制等。ExceptionTranslationFilter
: 捕获安全过滤器链中抛出的AccessDeniedException
和AuthenticationException
,并触发相应的入口点 (AuthenticationEntryPoint
) 或拒绝访问处理器 (AccessDeniedHandler
)。FilterSecurityInterceptor
: 这是授权决策的核心。它从SecurityContextHolder
获取Authentication
对象,然后使用AccessDecisionManager
基于配置的安全规则(SecurityMetadataSource
,通常来自@PreAuthorize
,@Secured
,http.authorizeRequests()
等)决定是否允许访问目标资源。如果拒绝,则抛出AccessDeniedException
。(注意:虽然名字叫Interceptor
,但它是一个Filter
! 这是历史原因造成的命名)CsrfFilter
: 提供对 CSRF 攻击的保护。LogoutFilter
: 处理注销请求 (POST /logout
)。
拦截器在 Spring Security 中的角色(较少)
在 Spring Security 本身的核心功能实现中,直接使用 HandlerInterceptor
的情况相对较少。安全的核心逻辑(特别是认证和授权)必须在请求到达 Controller 之前完成,这天然适合在过滤器链中实现。
然而,拦截器可以在与安全相关的辅助功能或特定于 Controller 的安全增强方面发挥作用:
- 审计日志 (Auditing): 在拦截器的
preHandle
或postHandle
中记录谁(从SecurityContextHolder
获取Authentication
)在什么时候访问了哪个 Controller 方法 (HandlerMethod
)。 - 细粒度的后处理: 在
postHandle
中基于安全上下文修改ModelAndView
(例如,根据用户角色在模型中设置不同的视图标志)。 - 自定义逻辑与 Controller 方法紧密结合: 如果需要基于即将执行的 Controller 方法或其注解进行非常特定的安全检查或处理,且这个逻辑不适合放在全局安全规则(
@PreAuthorize
)或 AOP 中,可以考虑使用拦截器。但要谨慎,因为此时请求已经通过了主要的FilterSecurityInterceptor
授权检查。 - 清理或资源释放: 在
afterCompletion
中执行一些与安全相关的清理工作(虽然过滤器通常也能做)。
面试回答要点与建议
清晰区分概念:
- 强调 Filter 是 Servlet 规范,作用于容器层,在
DispatcherServlet
之前;Interceptor 是 Spring MVC 组件,作用于DispatcherServlet
内部,围绕 Controller 方法执行。 - Spring Security 的核心安全机制(认证、授权)必须构建在 Filter 上,因为它们需要在请求进入 Spring MVC 核心流程前完成。
- 明确指出
FilterSecurityInterceptor
虽然叫 Interceptor,但它是一个Filter
。
- 强调 Filter 是 Servlet 规范,作用于容器层,在
阐述 Spring Security 的过滤器链机制:
- 提到
FilterChainProxy
作为总入口。 - 解释
SecurityFilterChain
的作用(匹配请求路径)。 - 列举几个关键的安全过滤器及其作用(
SecurityContextPersistenceFilter
,UsernamePasswordAuthenticationFilter
,ExceptionTranslationFilter
,FilterSecurityInterceptor
,CsrfFilter
)。
- 提到
说明拦截器的适用场景(在安全上下文中):
- 主要用于辅助功能(如审计日志)或与 Controller 方法紧密相关的后处理。
- 强调在 Spring Security 本身中直接使用 Interceptor 较少,核心逻辑在 Filter 链。
执行顺序的重要性:
- 明确画出或描述请求经过
Servlet Filter(s)
->Spring Security FilterChain (via FilterChainProxy)
->DispatcherServlet
->Spring MVC Interceptor(s)
->Controller
的流程。特别指出 Spring Security 的 Filter 在 Interceptor 之前执行。
- 明确画出或描述请求经过
依赖注入:
- 指出 Interceptor 作为 Spring Bean 可以方便地使用 DI,而原生的 Filter 不能直接使用 Spring DI(需要额外配置,如
DelegatingFilterProxy
或FilterRegistrationBean
结合 Spring 管理的 Filter Bean)。
- 指出 Interceptor 作为 Spring Bean 可以方便地使用 DI,而原生的 Filter 不能直接使用 Spring DI(需要额外配置,如
何时用哪个?
- 需要全局性的、在请求处理最早阶段介入的安全控制(认证、授权、CSRF)? -> Filter (特别是使用 Spring Security 提供的 Filter)。
- 需要访问 Spring MVC 特定对象(
HandlerMethod
,ModelAndView
)、进行基于 Controller 方法的细粒度操作(如审计)? -> Interceptor。 - 需要在视图渲染前后执行逻辑? -> Interceptor (
postHandle
,afterCompletion
)。 - 需要修改请求/响应内容本身(如包装
HttpServletRequest
)? -> Filter (Interceptor 无法修改请求体/响应体)。
常见误区澄清:
- 误区: “Spring Security 用 Interceptor 做授权。” 澄清: 核心授权是
FilterSecurityInterceptor
(一个Filter
!) 做的。 - 误区: “Interceptor 可以做认证。” 澄清: 理论上可以,但极其不推荐。认证必须在更早的 Filter 阶段完成。在 Interceptor 做认证太晚,且绕过 Spring Security 的核心机制,会导致漏洞和不一致。
- 误区: “Interceptor 可以替代 Filter。” 澄清: 不能。作用范围和能力不同。它们是互补的。
- 误区: “Spring Security 用 Interceptor 做授权。” 澄清: 核心授权是
示例面试回答结构
“在 Java Web 应用和 Spring Security 中,过滤器 (Filter
) 和拦截器 (HandlerInterceptor
) 都是处理 HTTP 请求响应的组件,但层次和职责不同。
过滤器 (
Filter
) 是 Servlet 规范定义的,工作在 Servlet 容器层面。任何请求进入容器后,响应离开容器前,都会经过配置的过滤器链。它们能修改请求和响应,并能中断链。Spring Security 的核心安全功能完全建立在过滤器链之上。关键组件FilterChainProxy
本身就是一个Filter
,它内部管理着多个SecurityFilterChain
,每个链包含一系列安全过滤器,例如:SecurityContextPersistenceFilter
:管理安全上下文(用户认证信息)。UsernamePasswordAuthenticationFilter
:处理表单登录。ExceptionTranslationFilter
:处理认证授权异常。FilterSecurityInterceptor
:核心的授权过滤器,决定当前用户是否有权访问资源。CsrfFilter
:防范 CSRF 攻击。 这些过滤器必须在请求到达 Spring MVC 的DispatcherServlet
(以及任何 Controller) 之前执行安全检查。
拦截器 (
HandlerInterceptor
) 是 Spring MVC 框架定义的,工作在DispatcherServlet
内部。它们在 Controller 方法执行的前(preHandle
)、后(postHandle
)、以及整个请求完成后(afterCompletion
)被调用。它们能访问 Spring MVC 对象(如HandlerMethod
),方便使用 Spring DI,但不能修改原始请求/响应体内容。在 Spring Security 的核心功能实现中,拦截器使用较少,因为安全决策需要在更早的 Filter 阶段完成。拦截器更多用于:- 审计日志(记录哪个认证用户访问了哪个 Controller 方法)。
- 基于安全上下文的视图模型修改。
- 与特定 Controller 方法相关的后处理逻辑。
执行顺序上: HTTP Request -> Servlet Filters (包括 FilterChainProxy
和 Spring Security 内部过滤器) -> DispatcherServlet
-> Spring MVC Interceptors (preHandle
) -> Controller -> Interceptors (postHandle
) -> View Render -> Interceptors (afterCompletion
) -> Servlet Filters (响应处理) -> HTTP Response。
总结:对于安全,认证授权等核心机制必须通过过滤器(特别是 Spring Security 的过滤器链)在请求进入 MVC 核心前完成。拦截器更适合 MVC 内部的、与 Controller 方法执行生命周期紧密相关的辅助性功能。两者协同工作,但职责清晰不同。”
记住,结合具体的过滤器名称(尤其是 FilterSecurityInterceptor
)和清晰的执行流程图(即使在脑中描述)会让你的回答更有说服力。祝你面试顺利!
📜文末寄语
- 🟠关注我,获取更多内容。
- 🟡技术动态、实战教程、问题解决方案等内容持续更新中。
- 🟢《全栈知识库》技术交流和分享社区,集结全栈各领域开发者,期待你的加入。
- 🔵加入开发者的《专属社群》,分享交流,技术之路不再孤独,一起变强。
- 🟣点击下方名片获取更多内容🍭🍭🍭👇