责任链模式在spring security过滤器链中的应用

news/2024/11/28 6:19:40/

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许多个对象按照顺序处理请求,并且每个对象可以选择自己是否处理该请求或将其传递给下一个对象。

在Spring Security中,责任链模式得到了广泛应用,特别是在其过滤器链(Filter Chain)机制中。

一、Spring Security过滤器链概述

Spring Security中的过滤器链是保护Web应用程序的核心组件之一。它是一条由多个过滤器组成的序列,这些过滤器按照特定顺序执行,用于处理HTTP请求和响应。每当客户端向应用程序发送请求时,请求首先会经过Spring Security的过滤器链。过滤器链中的过滤器会按顺序执行,每个过滤器都有机会处理请求和响应。如果过滤器允许请求继续,则请求会被转发到下一个过滤器或最终到达应用程序的控制器。

二、责任链模式在过滤器链中的应用 

  • 过滤器链的构成

    • Spring Security的过滤器链包含多种过滤器,如:UsernamePasswordAuthenticationFilter(用于处理基于用户名和密码的身份验证)、AbstractAuthenticationProcessingFilter(抽象类,是大多数身份验证过滤器的基类)、SecurityContextPersistenceFilter(负责加载和保存SecurityContext)、RememberMeAuthenticationFilter(处理基于“记住我”功能的身份验证)、CsrfFilter(处理跨站请求伪造保护)以及FilterSecurityInterceptor(执行访问决策)等。
  • 责任链模式的实现

    • 在Spring Security中,每个过滤器都实现了特定的安全功能,并且它们按照配置的顺序串联在一起,形成了一个过滤器链。
    • 当请求到达时,它首先被传递给链中的第一个过滤器。该过滤器会根据其逻辑判断是否需要处理该请求。如果需要,则进行处理;如果不需要或处理完成后需要继续传递,则将该请求传递给链中的下一个过滤器。
    • 这种机制允许每个过滤器专注于自己的安全功能,而无需关心其他过滤器的实现细节。同时,它也提供了更大的灵活性和可扩展性,因为可以通过添加、删除或重新排序过滤器来轻松地修改安全策略。
  • 关键过滤器的功能

    • UsernamePasswordAuthenticationFilter:用于处理基于用户名和密码的身份验证。它通常处理POST请求到/login端点。
    • SecurityContextPersistenceFilter:负责加载和保存SecurityContext。SecurityContext包含当前用户的安全上下文,如已认证的用户主体。
    • FilterSecurityInterceptor:执行访问决策。它根据配置的AccessDecisionManagerAccessDecisionVoter来决定用户是否有权访问某个资源。

三、自定义过滤器

在Spring Security中,自定义过滤器的实现是责任链模式的一个典型应用。通过创建并注册自定义过滤器,你可以将特定的安全逻辑插入到过滤器链中,从而在请求处理过程中执行额外的操作。

以下是一个简单的示例,展示如何创建自定义过滤器并将其集成到Spring Security的过滤器链中。

假设我们需要创建一个自定义过滤器,用于记录每个请求的URI和HTTP方法。以下是如何实现这个自定义过滤器并将其添加到Spring Security的过滤器链中的步骤。 

创建自定义过滤器

首先,你需要创建一个实现javax.servlet.Filter接口的类。在这个类中,你将覆盖doFilter方法以执行你的自定义逻辑。

java">import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.Filter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;public class CustomLoggingFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 初始化逻辑(可选)}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;String uri = httpRequest.getRequestURI();String method = httpRequest.getMethod();// 记录请求的URI和HTTP方法System.out.println("Request URI: " + uri + ", Method: " + method);// 将请求传递给过滤器链中的下一个过滤器chain.doFilter(request, response);}@Overridepublic void destroy() {// 销毁逻辑(可选)}
}

注册自定义过滤器到Spring Security

接下来,你需要将自定义过滤器注册到Spring Security的过滤器链中。这通常是通过配置类来实现的。

java">import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;@Configuration
@EnableWebSecurity
public class SecurityConfig {@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.addFilterBefore(customLoggingFilter(), UsernamePasswordAuthenticationFilter.class)// 其他安全配置....authorizeRequests().anyRequest().authenticated().and().formLogin() // 如果使用表单登录,则启用它.and().httpBasic(); // 启用HTTP Basic(可选)return http.build();}@Beanpublic CustomLoggingFilter customLoggingFilter() {return new CustomLoggingFilter();}
}

在这个配置类中,我们使用了HttpSecurity来配置Spring Security。通过调用addFilterBefore方法,我们将自定义过滤器CustomLoggingFilter添加到了UsernamePasswordAuthenticationFilter之前。这意味着在身份验证之前,我们的自定义过滤器将首先执行并记录请求的URI和HTTP方法。

运行应用程序

现在,当你运行应用程序并发送请求时,你应该会在控制台中看到自定义过滤器记录的请求信息。

 

在Spring Security中每个过滤器(包括自定义过滤器)都是链中的一个节点,它们按照配置的顺序依次执行。每个过滤器都有机会处理请求,并且可以选择将请求传递给链中的下一个过滤器或执行其他操作(如拒绝访问、重定向等)。这种机制使得Spring Security能够灵活地处理各种安全需求,同时保持了代码的清晰和可维护性。

 


http://www.ppmy.cn/news/1550548.html

相关文章

C++多线程——线程

1、线程与进程 进程是一个具有独立功能程序的运行实体,如某一个程序,运行时便产生一个进程;通常一个进程包含一个或多个线程。普通C程序多是只含有一个线程的进程,但是大多数情况下遇到的是多线程的进程。 线程与进程都是操作系统…

IDEA自定义帆软函数步骤详解

前序: 在帆软里面有很多内置函数可以供我们使用,比如计算总和的SUM()函数, 计算绝对值的ABS()函数等等,但是很多时候随着业务的复杂性,这些函数已经不满足于我们复杂的计算要求,所以我们可以自定义一些函数来满足我们的需求。 自定义函数列表 (一)如何新增自定义函数 …

urllib3只支持OpenSSL1.1.1

1 现象 urllib3 v2.0 only supports OpenSSL 1.1.1, currently the ssl module is compiled with OpenSSL 1.1.0j 20 Nov 2018.2 解决方法 降低urllib3的版本。 从pycharm中,先卸载原有的urllib3版本。 菜单“File|Settings|Project:python|Project Interprete…

探寻嵌入式系统的发展之路与趋势展望

目录 一、嵌入式系统的发展历程 1.1. 早期阶段(20世纪40年代至70年代初) 1.1.1. 起源与背景 1.1.2. 特点 1.1.3. 应用领域 1.1.4. 发展里程碑 1.2. 单片机时代(20世纪70年代初至80年代末) 1.2.1. 硬件 1.2.2. 软件 1.2.…

tomcat控制台中文乱码的解决方法

将tocamt conf配置目录下的logging.properties文件中如图所示的utf-8改为GBK即可。

搭建AI知识库:打造坚实的团队知识堡垒

在信息爆炸的时代,企业面临着知识管理的挑战。团队知识堡垒的构建,即搭建一个高效的AI知识库,对于保护和利用知识资产、提升团队协作效率和创新能力至关重要。本文将探讨搭建AI知识库的重要性、策略以及如何通过这一系统打造坚实的团队知识堡…

第五章 if语句优化之工厂策略模式+Supplier接口(四)

目录 一、引言 二、问题代码 三、优化后的代码 一、引言 我们在实际项目开发中,一定会充斥着大量这种if elseif的等号条件判断语句,这种写法我们称之为流水账。随着后续判断条件逐步递增,执行体的业务功能越来越复杂、代码量越来越多时&am…

深入解析 EasyExcel 组件原理与应用

EasyExcel 是一个为了简化 Excel 操作,而封装的一个 Java 工具库。它支持读写 Excel 97-2003 和 Excel 2007 格式的文件。 以下是一个使用 EasyExcel 读取 Excel 文件的简单示例: import com.alibaba.excel.EasyExcel; import com.alibaba.excel.read…