Spring Security 是独立于 Spring MVC 的安全门卫,通过 DelegatingFilterProxy 和 FilterChainProxy 构建双代理结构,在 DispatcherServlet 前拦截请求;非法请求在 SecurityFilterChain 中被直接阻断并返回 401/403,永不进入 MVC 流程。

Spring MVC 本身不负责安全拦截,真正实现“在 Filter 层阻断非法请求、防止进入 DispatcherServlet”的,是 Spring Security —— 它不是 Spring MVC 的插件,而是独立运行在 Servlet 容器最外层的安全门卫。关键在于理解它的双代理结构和过滤器链执行时机。
Filter 层拦截发生在 DispatcherServlet 之前
请求流程是:客户端 → Servlet 容器 → DelegatingFilterProxy → FilterChainProxy → SecurityFilterChain(含多个 Security Filter)→ DispatcherServlet
也就是说,所有请求必须先穿过 Spring Security 的过滤器链,认证失败或权限不足时,直接返回响应(如 401/403 或重定向登录页),根本不会到达 DispatcherServlet,更不会触发 Controller、Interceptor 或 HandlerMapping。
立即学习“Java免费学习笔记(深入)”;
核心机制:DelegatingFilterProxy + FilterChainProxy
-
DelegatingFilterProxy是 web.xml 或 Spring Boot 自动注册的 Servlet Filter,由容器管理,但逻辑委托给 Spring 容器里的FilterChainProxy。 -
FilterChainProxy不是一个 Filter,而是一个“过滤器链调度器”,它持有多个SecurityFilterChain实例,并根据请求路径(如/api/**、/admin/**)匹配对应链。 - 每条
SecurityFilterChain内部是一组严格排序的Filter(如UsernamePasswordAuthenticationFilter、BasicAuthenticationFilter、FilterSecurityInterceptor),它们才是真正执行校验、认证、授权的组件。
如何让非法请求在 Filter 层就被拦下?
-
✅ 配置
HttpSecurity时明确拒绝访问@Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers("/public/**").permitAll() .requestMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated() // 所有其他请求需登录 ); return http.build(); }当请求
/admin/user但用户未登录或无 ADMIN 角色时,FilterSecurityInterceptor会在doFilter()中抛出AccessDeniedException或AuthenticationException,由ExceptionTranslationFilter捕获并直接返回错误响应,不放行到 DispatcherServlet。 -
✅ 自定义 Filter 必须注入到 SecurityFilterChain 中(而非普通 Filter)
如果你写了一个TokenValidateFilter,想让它参与安全决策:- ❌ 不要通过
FilterRegistrationBean注册为普通 Servlet Filter(它会绕过 Security 流程,可能在 Security Filter 之前或之后执行,顺序不可控); - ✅ 正确方式是用
addFilterBefore()/addFilterAfter()将其插入SecurityFilterChain:http.addFilterBefore(new MyTokenFilter(), UsernamePasswordAuthenticationFilter.class);
这样它就成为 Security 过滤器链的一环,享有统一异常处理、上下文共享(如
SecurityContextHolder),且天然在 DispatcherServlet 之前执行。
- ❌ 不要通过
✅ 确保没有 bypass Spring Security 的直连路径
常见漏洞:静态资源路径(如/static/**)没被 Security 管理;JSP 页面被直接访问(绕过 Controller);或WebMvcConfigurer中错误地放行了不该放行的路径。应统一用authorizeHttpRequests管理所有 HTTP 路径,包括/favicon.ico、/error等。
为什么 Interceptor 不能替代 Filter 层拦截?
Spring MVC 的 HandlerInterceptor 在 DispatcherServlet 分发后才生效,此时请求已进入 Spring MVC 生命周期 —— HandlerMapping 已匹配 Controller,HandlerAdapter 准备调用方法。即使 preHandle() 返回 false,也只是中断 MVC 流程,但日志、参数解析、甚至部分业务逻辑可能已执行。真正的“零接触”防护,只能靠 Filter 层完成。
不复杂但容易忽略。


















