news 2026/6/23 18:53:12

设计模式:责任链模式(Spring Security)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
设计模式:责任链模式(Spring Security)

目录

一、核心角色对应(责任链模式)

二、核心架构:双层责任链设计

1. 外层:FilterChainProxy(全局过滤器入口)

2. 内层:SecurityFilterChain(具体过滤器链)

三、核心流程(以表单登录为例)

关键特点:

四、代码示例:自定义过滤器链

步骤 1:自定义认证过滤器(具体处理者)

步骤 2:配置过滤器链(责任链管理器)

步骤 3:核心业务(Controller,责任链终点)

五、核心过滤器(内置具体处理者)

六、责任链的核心实现(源码简化)

1. FilterChainProxy(外层管理器)

2. 关键逻辑:

七、Spring Security 责任链的核心特点

1. 高度可定制

2. 中断性与容错性

3. 解耦性

八、典型应用场景

九、与 Spring MVC 拦截器链的区别

总结


Spring Security 的核心架构完全基于责任链模式设计,其核心载体是过滤器链(SecurityFilterChain—— 将认证、授权、防护等安全逻辑拆分为独立的过滤器(Filter),请求沿过滤器链按序执行,每个过滤器负责单一安全职责,最终实现完整的安全校验流程。

核心目标:将复杂的安全逻辑解耦为可插拔的过滤器组件,支持灵活扩展和定制(如新增验证码校验、JWT 认证、接口限流等)

一、核心角色对应(责任链模式)

责任链模式角色Spring Security 对应实现核心职责
抽象处理者(Handler)javax.servlet.Filter(Servlet 过滤器)/OncePerRequestFilter定义过滤器核心方法doFilter(),约定请求处理规则(Spring Security 过滤器多继承OncePerRequestFilter保证单次请求仅执行一次)
具体处理者内置过滤器(如UsernamePasswordAuthenticationFilterJwtAuthenticationFilter)/ 自定义过滤器实现特定安全逻辑(认证、授权、CSRF 防护等),通过chain.doFilter()传递请求
责任链管理器FilterChainProxy+SecurityFilterChainFilterChainProxy是顶级入口,匹配请求对应的SecurityFilterChain,触发过滤器链执行
请求对象HttpServletRequest/HttpServletResponse被过滤器链处理的核心对象
最终处理者目标资源(Controller / 静态资源)过滤器链执行完成后,请求传递到核心业务逻辑

二、核心架构:双层责任链设计

Spring Security 的责任链分为两层,保证 “多规则适配 + 顺序执行”:

1. 外层:FilterChainProxy(全局过滤器入口)

FilterChainProxy是 Spring Security 注册到 Servlet 容器的唯一过滤器(通过DelegatingFilterProxy适配),其核心作用是:

  • 根据请求路径匹配对应的SecurityFilterChain(支持多套过滤器链,如/api/**一套、/admin/**另一套);
  • 触发匹配到的SecurityFilterChain执行。

2. 内层:SecurityFilterChain(具体过滤器链)

每个SecurityFilterChain包含一组有序的过滤器(List<Filter>),是真正执行安全逻辑的责任链,例如:

plaintext

UsernamePasswordAuthenticationFilter(表单登录认证)→ BasicAuthenticationFilter(Basic 认证)→ JwtAuthenticationFilter(JWT 认证)→ FilterSecurityInterceptor(授权校验)→ ExceptionTranslationFilter(异常处理)

三、核心流程(以表单登录为例)

plaintext

客户端请求 → Tomcat → DelegatingFilterProxy → FilterChainProxy → 匹配 SecurityFilterChain → 执行过滤器链: 1. CsrfFilter(CSRF 防护)→ 2. UsernamePasswordAuthenticationFilter(表单登录认证)→ 3. BasicAuthenticationFilter(Basic 认证,跳过)→ 4. FilterSecurityInterceptor(授权校验)→ 5. ExceptionTranslationFilter(异常处理,无异常则跳过)→ 传递到 DispatcherServlet → Controller(核心业务)

关键特点:

  • 顺序性:过滤器按固定顺序执行(可通过配置调整),例如 “认证过滤器必须在授权过滤器前执行”;
  • 中断性:过滤器可中断链(如认证失败直接返回 401,不调用chain.doFilter());
  • 匹配性:不同请求路径可匹配不同过滤器链(如/login走表单登录链,/api走 JWT 认证链)。

四、代码示例:自定义过滤器链

步骤 1:自定义认证过滤器(具体处理者)

实现 JWT 认证过滤器,作为责任链的具体处理者:

java

运行

@Component public class JwtAuthenticationFilter extends OncePerRequestFilter { @Autowired private JwtTokenProvider jwtTokenProvider; @Autowired private AuthenticationManager authenticationManager; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 1. 提取 Token String token = request.getHeader("Authorization"); if (token == null || !token.startsWith("Bearer ")) { filterChain.doFilter(request, response); // 无 Token,传递给下一个过滤器 return; } token = token.substring(7); // 2. 校验 Token try { String username = jwtTokenProvider.extractUsername(token); if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { // 3. 认证通过,存入 SecurityContext Authentication authentication = jwtTokenProvider.getAuthentication(token); SecurityContextHolder.getContext().setAuthentication(authentication); System.out.println("JwtAuthenticationFilter:JWT 认证通过,用户:" + username); } } catch (Exception e) { // 认证失败,中断链(返回 401) response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.getWriter().write("JWT 认证失败:" + e.getMessage()); return; } // 4. 传递给下一个过滤器 filterChain.doFilter(request, response); } }

步骤 2:配置过滤器链(责任链管理器)

通过SecurityFilterChain构建自定义责任链,指定过滤器顺序:

java

运行

@Configuration @EnableWebSecurity public class SecurityConfig { @Autowired private JwtAuthenticationFilter jwtAuthenticationFilter; @Autowired private CustomAccessDeniedHandler accessDeniedHandler; // 自定义授权失败处理器 @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http // 关闭默认的 CSRF(测试环境,生产需开启) .csrf(csrf -> csrf.disable()) // 配置请求授权规则 .authorizeHttpRequests(auth -> auth .requestMatchers("/login").permitAll() // 登录接口放行 .requestMatchers("/api/admin/**").hasRole("ADMIN") // 管理员接口需 ADMIN 角色 .anyRequest().authenticated() // 其他请求需认证 ) // 异常处理 .exceptionHandling(ex -> ex .accessDeniedHandler(accessDeniedHandler) // 授权失败处理 .authenticationEntryPoint((request, response, authException) -> { // 认证失败处理 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.getWriter().write("请先认证"); }) ) // 添加自定义过滤器:插入到 UsernamePasswordAuthenticationFilter 之后 .addFilterAfter(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); return http.build(); } // 认证管理器(用于处理用户认证) @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception { return config.getAuthenticationManager(); } // 密码编码器 @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }

步骤 3:核心业务(Controller,责任链终点)

java

运行

@RestController @RequestMapping("/api") public class UserController { @GetMapping("/user") public String getUser() { return "普通用户接口"; } @GetMapping("/admin/user") public String getAdminUser() { return "管理员接口"; } }

五、核心过滤器(内置具体处理者)

Spring Security 内置了数十个过滤器,覆盖所有核心安全场景,以下是最常用的:

过滤器核心职责执行顺序(关键)
CsrfFilterCSRF 防护,验证 CSRF Token靠前(先防护后认证)
UsernamePasswordAuthenticationFilter表单登录认证,处理/login请求的用户名密码认证类过滤器核心
BasicAuthenticationFilterBasic 认证,解析请求头中的Authorization: Basic xxx表单认证之后
JwtAuthenticationFilterJWT 认证(需自定义 / 引入 spring-security-oauth2)可插入到认证过滤器链
FilterSecurityInterceptor授权校验,匹配@PreAuthorize/ 角色 / 权限规则认证之后(最后一个核心过滤器)
ExceptionTranslationFilter捕获安全异常(如AuthenticationException/AccessDeniedException),转换为 HTTP 响应授权过滤器之前
LogoutFilter处理登出请求,清理SecurityContext认证过滤器之前

六、责任链的核心实现(源码简化)

1. FilterChainProxy(外层管理器)

java

运行

public class FilterChainProxy extends GenericFilterBean { private List<SecurityFilterChain> filterChains; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; // 1. 匹配当前请求对应的 SecurityFilterChain SecurityFilterChain filterChain = getMatchingFilterChain(req, res); if (filterChain == null) { chain.doFilter(req, res); // 无匹配链,直接传递 return; } // 2. 执行匹配到的过滤器链 VirtualFilterChain virtualFilterChain = new VirtualFilterChain(chain, filterChain.getFilters()); virtualFilterChain.doFilter(req, res); } // 内部类:封装具体过滤器链的执行 private static class VirtualFilterChain implements FilterChain { private final FilterChain originalChain; private final List<Filter> filters; private int currentPosition = 0; public VirtualFilterChain(FilterChain originalChain, List<Filter> filters) { this.originalChain = originalChain; this.filters = filters; } @Override public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (currentPosition == filters.size()) { // 所有过滤器执行完成,传递到原始链(DispatcherServlet) originalChain.doFilter(request, response); return; } // 按顺序执行下一个过滤器 currentPosition++; Filter nextFilter = filters.get(currentPosition - 1); nextFilter.doFilter(request, response, this); } } }

2. 关键逻辑:

  • VirtualFilterChain是责任链的核心执行器,通过currentPosition记录当前执行的过滤器索引;
  • 每个过滤器执行完后调用virtualFilterChain.doFilter(),实现请求的 “链式传递”;
  • 所有过滤器执行完成后,才会调用originalChain.doFilter()传递到 DispatcherServlet。

七、Spring Security 责任链的核心特点

1. 高度可定制

  • 顺序调整:通过addFilterBefore()/addFilterAfter()/addFilterAt()调整过滤器顺序(如将 JWT 过滤器插入到表单认证过滤器之后);
  • 链的拆分:多套SecurityFilterChain适配不同路径的安全规则(如前台 / 后台不同认证方式);
  • 过滤器扩展:自定义过滤器只需继承OncePerRequestFilter,注册到链中即可,无需修改原有逻辑。

2. 中断性与容错性

  • 中断链:过滤器可通过 “不调用chain.doFilter()” 中断请求(如认证失败直接返回 401);
  • 异常处理ExceptionTranslationFilter捕获链中异常,保证单一异常出口,避免链中断导致的资源泄漏。

3. 解耦性

  • 每个过滤器仅关注单一职责(如认证、授权、CSRF),符合 “单一职责原则”;
  • 核心业务(Controller)无需耦合安全逻辑,通过过滤器链透明增强。

八、典型应用场景

  1. 多认证方式:同时支持表单登录、JWT 认证、OAuth2 认证(不同过滤器处理);
  2. 精细化授权:基于角色(hasRole)、权限(hasPermission)、IP 白名单的授权校验;
  3. 安全防护:CSRF 防护、XSS 过滤、接口限流(自定义过滤器实现);
  4. 异常统一处理:认证 / 授权失败返回标准化 JSON 响应;
  5. 第三方集成:集成 CAS、LDAP 等认证体系(新增对应过滤器)。

九、与 Spring MVC 拦截器链的区别

维度Spring Security 过滤器链Spring MVC HandlerInterceptor 链
核心目的安全逻辑(认证、授权、防护)通用请求增强(日志、参数处理)
执行时机DispatcherServlet 之前(Servlet 容器层)DispatcherServlet 内部
扩展能力可拦截所有 Web 请求(包括静态资源)仅拦截 Controller 请求
依赖原生 Servlet Filter,无 Spring 依赖依赖 Spring 上下文,可注入 Bean
中断方式不调用chain.doFilter()preHandle返回 false

总结

Spring Security 是责任链模式在 “安全领域” 的极致落地:

  1. 核心载体FilterChainProxy+SecurityFilterChain构成双层责任链,实现 “多规则匹配 + 顺序执行”;
  2. 核心逻辑:每个过滤器是独立的安全处理单元,通过chain.doFilter()传递请求,支持中断和扩展;
  3. 核心价值:将复杂的安全逻辑解耦为可插拔的过滤器,适配不同场景的安全需求(如单体应用、微服务、前后端分离);
  4. 扩展关键:自定义过滤器只需继承OncePerRequestFilter,通过addFilterBefore/After插入到责任链中,无需修改框架源码。

掌握这一机制,是定制 Spring Security 安全规则(如 JWT 认证、自定义授权)的核心前提。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/19 8:12:55

设计模式:责任链模式(MyBatis)

目录 一、核心角色对应&#xff08;责任链模式&#xff09; 二、MyBatis 责任链的核心拦截点 三、责任链执行流程&#xff08;以 StatementHandler 为例&#xff09; 1. 整体流程 2. 关键环节&#xff1a;嵌套代理构建责任链 四、代码示例&#xff1a;自定义插件实现责任…

作者头像 李华
网站建设 2026/6/12 5:47:40

网络安全求职秘籍:从漏洞挖掘到应急响应,新手到大神的通关手册

【收藏必备】网络安全面试宝典&#xff1a;从OWASP到内网渗透&#xff0c;小白到专家的进阶指南 本文全面整理网络安全面试题&#xff0c;涵盖HVV、OWASP Top 10漏洞原理与修复方法。详细讲解内网渗透技术、权限维持方法、Windows/Linux系统提权技巧&#xff0c;以及渗透测试流…

作者头像 李华
网站建设 2026/6/19 3:42:06

SSLPinDetect:面向Android安全分析的先进SSL Pinning检测工具

在移动应用安全不断演变的格局中&#xff0c;SSL Pinning已成为抵御中间人攻击的关键防御机制。然而&#xff0c;对于安全研究人员和渗透测试人员来说&#xff0c;识别这些实现可能是一项耗时且复杂的任务。 我为什么要创建 SSLPinDetect 我创建此工具的目的是为了在扫描应用中…

作者头像 李华
网站建设 2026/6/12 18:55:47

Open-AutoGLM部署避坑指南:3大关键步骤决定你能否成功运行

第一章&#xff1a;Open-AutoGLM部署前的环境准备与认知 在部署 Open-AutoGLM 之前&#xff0c;充分理解其运行依赖和系统要求是确保后续流程顺利的关键。该框架基于 PyTorch 构建&#xff0c;依赖 CUDA 加速进行高效推理&#xff0c;因此需提前配置兼容的硬件与软件环境。 系…

作者头像 李华
网站建设 2026/6/14 6:16:05

做1688批发系统5年,被商品详情API坑到连夜改代码的实战手记

在电商开发圈混了快十年&#xff0c;1688的商品详情API绝对是最“特立独行”的存在。作为批发平台&#xff0c;它的接口返回里藏着太多零售平台没有的“暗门”——从阶梯价的诡异格式到混批规则的嵌套逻辑&#xff0c;每次对接都像拆盲盒。今天就把这些年踩过的坑、攒的实战代码…

作者头像 李华