Spring Security 的工作原理/总体架构

目录

1、过滤器的视角

2、DelegatingFilterProxy 委派过滤器代理(类)

2、FilterChainProxy 过滤器链代理(类)

4、SecurityFilterChain 安全过滤器链(接口)

5、Security Filters 安全过滤器实例

6、Spring Security 如何处理安全异常?

7、在认证的时候保存用户请求


        // 释义、解读和思考

1、过滤器的视角

        Spring Security 对 Servlet 支持基于 Servlet 过滤器。下图显示了单个HTTP请求的处理程序的典型分层。

        客户端向应用程序发送请求,容器根据请求 URI 的路径创建一个 FilterChain,其中包含过滤器实例和处理 HttpServletRequest 的 Servlet。// 过滤器链式顺序执行的,具有有序性

        因为 Filter 会影响下游的 Filter 实例和 Servlet,所以调用每个 Filter 的顺序非常重要

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
    // 省略...
    chain.doFilter(request, response); 
    // 省略...
}

        // doFilter 方法中有一个 FilterChain 入参,FilterChain 也是一个接口,既然 FilterChain 是一个过滤器链,那么它的实现类中肯定包含有一个 Filter 列表(持有一个或多个Filter 对象)。看源码

        // Spring Security 利用过滤器链来实现身份验证和授权

2、DelegatingFilterProxy 委派过滤器代理(类)

        Spring 提供了一个名为 DelegatingFilterProxy 的过滤器代理类,它是 Servlet 容器的生命周期和 Spring 的 ApplicationContext 之间架桥。//这个类是一个通用的过滤器实例

        // 在Spring 中,Spring 管理过滤器的生命周期,所以 Filter 实例也是 Spring 中的一个Bean

        DelegatingFilterProxy 从 ApplicationContext 中查找 Bean Filter-0,然后调用 Bean Filter-0,下面的代码展示了这一过程:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
    //获取Bean
	Filter delegate = getFilterBean(someBeanName);
	delegate.doFilter(request, response);
}

        // 总结:DelegatingFilterProxy 这个类就是一个过滤器实例,Spring 通过这个过滤器,去实现一系列的认证和授权操作。

        // 深刻认识下,想想这种做法。

2、FilterChainProxy 过滤器链代理(类)

        Spring Security 的 Servlet 支持包含在 FilterChainProxy 中。

        FilterChainProxy 是 Spring Security 提供的一个特殊过滤器,它允许通过 SecurityFilterChain 向多个过滤器实例委托。FilterChainProxy 是一个Bean,它通常被封装在 DelegatingFilterProxy中。

        //见名知意,过滤器链的代理 FilterChainProxy 中会持有过滤器链的对象

public class FilterChainProxy extends GenericFilterBean {

	private static final Log logger = LogFactory.getLog(FilterChainProxy.class);

	private final static String FILTER_APPLIED = FilterChainProxy.class.getName().concat(
			".APPLIED");

    // SecurityFilterChain 对象列表
	private List<SecurityFilterChain> filterChains;

    //省略...
}

        // FilterChainProxy -> DelegatingFilterProxy,可以猜想 DelegatingFilterProxy 中的这个 delegate 是不是就是 FilterChainProxy 的实例?源码见分晓

​
public class DelegatingFilterProxy extends GenericFilterBean {
    @Nullable
    private String contextAttribute;
    @Nullable
    private WebApplicationContext webApplicationContext;
    @Nullable
    private String targetBeanName;
    private boolean targetFilterLifecycle;
    @Nullable
    private volatile Filter delegate;  //这里有一个过滤器委托,proxy
    private final Object delegateMonitor;
    //省略...
}

4、SecurityFilterChain 安全过滤器链(接口)

        FilterChainProxy 使用 SecurityFilterChain 来确定应该为当前请求调用哪一个 Spring SecurityFilter 实例

        //选择过滤器链,在FilterChainProxy 中是这样做的

// 返回与提供的URL匹配的第一个过滤器链    
private List<Filter> getFilters(HttpServletRequest request) {
		for (SecurityFilterChain chain : filterChains) {
			if (chain.matches(request)) {
				return chain.getFilters();
			}
		}
		return null;
	}

//一些源码:
//SecurityFilterChain(接口) -> DefaultSecurityFilterChain(实现类) -> 持有RequestMatcher对象 -> matches方法
//RequestMatcher接口用来支持匹配HttpServletRequest的简单策略。匹配策略有很多,此处不多介绍
//RequestMatcher -> AntPathRequestMatcher(实现),servlet通过url路径进行匹配 

        下图显示了 SecurityFilterChain 的角色。

        SecurityFilterChain 中的 Filter 实例是在 FilterChainProxy 中进行注册的(而不是 DelegatingFilterProxy)。

    public FilterChainProxy(SecurityFilterChain chain) {
		this(Arrays.asList(chain));
	}

	public FilterChainProxy(List<SecurityFilterChain> filterChains) {
		this.filterChains = filterChains;
	}

        使用 FilterChainProxy 作为起点的优势://这些特点很重要,仔细看

  1. 这样做为 Spring Security 的所有 Servlet 支持提供了一个起点,如果试图对 Spring Security 的 Servlet 支持进行故障排除,那么在 FilterChainProxy 中添加一个调试点是一个很好的开始。//所有的过滤器都在这里进行注册,然后开始调用,过滤器的调用从FilterChainProxy选择一个过滤器链开始
  2. FilterChainProxy 是 Spring Security 使用的核心,它可以执行一些不可选的任务。例如,清除 SecurityContext 以避免内存泄漏,应用 Spring Security 的HttpFirewall 来保护应用程序免受某些类型的攻击。//不可选的任务,就是必须做的一些事情或者一些通用的功能
  3. 在确定何时调用 SecurityFilterChain 方面提供了更大的灵活性。在 Servlet 容器中,仅根据 URL 调用 Filter 实例。然而,FilterChainProxy 可以通过使用 RequestMatcher 接口,基于 HttpServletRequest 中的任何内容来确定调用。//方便做选择,RequestMatcher -> 匹配策略接口

        下图显示了多个 SecurityFilterChain 实例:

        在 Multiple SecurityFilterChain 图中,FilterChainProxy 决定应该使用哪个 SecurityFilterChain。

        这里有一些匹配规则: 

        FilterChainProxy 只会调用匹配到的第一个 SecurityFilterChain。如请求 URL 为: /api/messages/,它首先匹配的是 SecurityFilterChain-0(匹配规则:/api/**),因此只调用 SecurityFilterChain-0,即使它也匹配 SecurityFilterChain-n(匹配规则:/**)。//执行第一个匹配到的过滤器链

        如果请求 URL/messages/ ,它与SecurityFilterChain-0(匹配规则:/api/**)不匹配,因此 FilterChainProxy 会继续尝试每个 SecurityFilterChain。假设没有其他 SecurityFilterChain 实例匹配,则调用 SecurityFilterChain-n

        需要注意的是,每个 SecurityFilterChain 都是唯一的,并且可以进行单独配置。如果应用程序希望 Spring security 忽略某些请求,那么可以在 SecurityFilterChain 中不设置任何的安全过滤器实例。//SecurityFilterChain 这个里边可以没有任何过滤器,那就是不进行任何拦截

5、Security Filters 安全过滤器实例

        以下是 Spring Security 的过滤器排序的综合列表://按顺序排列的

  1. ForceEagerSessionCreationFilter
  2. ChannelProcessingFilter
  3. WebAsyncManagerIntegrationFilter
  4. SecurityContextPersistenceFilter
  5. HeaderWriterFilter
  6. CorsFilter
  7. CsrfFilter
  8. LogoutFilter
  9. OAuth2AuthorizationRequestRedirectFilter
  10. Saml2WebSsoAuthenticationRequestFilter
  11. X509AuthenticationFilter
  12. AbstractPreAuthenticatedProcessingFilter
  13. CasAuthenticationFilter
  14. OAuth2LoginAuthenticationFilter
  15. Saml2WebSsoAuthenticationFilter
  16. UsernamePasswordAuthenticationFilter
  17. DefaultLoginPageGeneratingFilter
  18. DefaultLogoutPageGeneratingFilter
  19. ConcurrentSessionFilter
  20. DigestAuthenticationFilter
  21. BearerTokenAuthenticationFilter
  22. BasicAuthenticationFilter
  23. RequestCacheAwareFilter
  24. SecurityContextHolderAwareRequestFilter
  25. JaasApiIntegrationFilter
  26. RememberMeAuthenticationFilter
  27. AnonymousAuthenticationFilter
  28. OAuth2AuthorizationCodeGrantFilter
  29. SessionManagementFilter
  30. ExceptionTranslationFilter  //异常处理过滤器
  31. FilterSecurityInterceptor
  32. SwitchUserFilter

        //这些过滤器的排序是Spring官方提供的,后来Spring可能觉得这样展示的意义不大,删去了这部分内容, 补充了一些从日志查看过滤器加载顺序的说明。(过滤器的加载顺序会在Info日志中打印,以实时加载为准)。

6、Spring Security 如何处理安全异常?

        //首先说,这里就是 Spring Security 的工作原理,重中之重,非常重要,虽然讲的是一个异常过滤器,但是实际上是一个执行流程。

        ExceptionTranslationFilter 允许将 AccessDeniedException 和 AuthenticationException 转换为 HTTP 响应。//两个异常,禁止访问 + 认证异常

        ExceptionTranslationFilter 作为安全过滤器之一,自动插入到 FilterChainProxy 中。

        下图显示了 ExceptionTranslationFilter 与其他组件的关系:

        首先,ExceptionTranslationFilter 调用 FilterChain.doFilter(request, response) 来调用应用程序的剩余部分,这里有两种情况,用户未经过认证以及用户被拒绝访问// Continue ProcessingRequest Normally -> 继续正常处理请求

        如果用户未经过身份验证或者抛出了 AuthenticationException,则启动身份验证

  1. 首先清除 SecurityContextHolder,这个是一个 Spring Security 中的一个核心类。
  2. RequestCache:保存 HttpServletRequest 请求,在身份验证成功后可以使用它重复原始请求。//也可以不保存,那么用户就需要重新去请求
  3. AuthenticationEntryPoint 用于从客户端获取请求凭据。例如,它可能重定向到登录页面或发送 WWW-Authenticate 报文头。//AuthenticationEntryPoint(接口) -> 比如重定向到登录页面,要求登录,执行从客户端获取请求凭据的策略

        //以上这三个类都给出了身份验证的大致流程,流程中给出了这些关键类的使用时机,描述了 Spring Security 的大致框架。

        如果是 AccessDeniedException,则拒绝访问。直接调用 AccessDeniedHandler 来处理拒绝访问。// AccessDeniedHandler(接口),也可以自定义处理策略

        如果应用程序没有抛出 AccessDeniedException AuthenticationException,则ExceptionTranslationFilter 不做任何事情。//这个过滤器只处理这两个异常

        ExceptionTranslationFilter 的伪代码逻辑如下:

try {
	filterChain.doFilter(request, response);
} catch (AccessDeniedException | AuthenticationException ex) { //捕获特定异常
	if (!authenticated || ex instanceof AuthenticationException) {
		startAuthentication(); //启动认证流程
	} else {
		accessDenied(); //决绝策略
	}
}

7、在认证的时候保存用户请求

        当用户请求资源时,如果没有经过身份验证,就需要保存请求信息,当身份验证成功后再重新执行该请求。在 Spring Security 中,通过使用 RequestCache 的实现来保存 HttpServletRequest。//RequestCache是一个接口,请求缓存策略可以有不同的实现

        RequestCacheAwareFilter 和 RequestCache 接口

        HttpServletRequest 保存在 RequestCache 中。当用户成功通过身份验证时,将使用 RequestCache 重新执行原始请求。

        RequestCacheAwareFilter 使用 RequestCache 来保存 HttpServletRequest。默认情况下,使用 HttpSessionRequestCache

        下面的代码演示了如何定制 RequestCache 的实现,该实现用于在参数 continue 存在的情况下检查保存请求的 HttpSession。//这里存储的是一个标记,通过RequestCacheAwareFilter过滤器使用

@Bean
DefaultSecurityFilterChain springSecurity(HttpSecurity http) throws Exception {
	HttpSessionRequestCache requestCache = new HttpSessionRequestCache();
	requestCache.setMatchingRequestParameterName("continue");
	http
		// ...
		.requestCache((cache) -> cache.requestCache(requestCache));
	return http.build();
}

        如果不希望在会话中存储用户未经身份验证的请求,可以使用 NullRequestCache 实现。//不保存会话信息,直接重定向到登录页

@Bean
SecurityFilterChain springSecurity(HttpSecurity http) throws Exception {
    RequestCache nullRequestCache = new NullRequestCache();
    http
        // ...
        .requestCache((cache) -> cache.requestCache(nullRequestCache));
    return http.build();
}

        至此,全文结束。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/43133.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于sklearn计算precision、recall等分类指标

文章目录 一、分类指标函数1.1 precision_score函数1.2 recall_score函数1.3 accuracy_score函数1.4 f1_score函数1.5 precision_recall_curve函数1.6 roc_curve函数1.7 roc_auc_score函数1.8 classification_report函数 二、二分类任务三、多分类任务3.1 Macro Average&#x…

Meta牵手Microsoft推出下一代Llama 2

官方消息 1、今天&#xff0c;我们将介绍 Llama 2 的可用性&#xff0c;这是我们的下一代开源大型语言模型。 2、Llama 2免费用于研究和商业用途。 3、Microsoft和 Meta 正在扩大他们的长期合作伙伴关系&#xff0c;Microsoft 是 Llama 2 的首选合作伙伴。 4、在技术、学术…

力扣 -- 122. 买卖股票的最佳时机 II

一、题目&#xff1a; 题目链接&#xff1a;122. 买卖股票的最佳时机 II - 力扣&#xff08;LeetCode&#xff09; 二、解题步骤 下面是用动态规划的思想解决这道题的过程&#xff0c;相信各位小伙伴都能看懂并且掌握这道经典的动规题目滴。 三、参考代码&#xff1a; clas…

Xcode 15 beta 4 (15A5195m) - Apple 平台 IDE

Xcode 15 beta 4 (15A5195m) - Apple 平台 IDE IDE for iOS/iPadOS/macOS/watchOS/tvOS/visonOS 请访问原文链接&#xff1a;https://sysin.org/blog/apple-xcode-15/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org visonOS …

基于ESP32-S3-BOX-Lite的语音合成与播报系统(esp-idf+WiFi+HTTPS+TTS)

目录 项目介绍硬件介绍项目设计开发环境及工程目录总体流程图硬件初始化WiFiHTTPS请求TTS语音合成与播报cJSON解析TTS初始化语音合成与播报 附加功能按键回调LVGL数据可视化显示 功能展示项目总结 &#x1f449; 【Funpack2-5】基于ESP32-S3-BOX-Lite的语音合成与播报系统 &…

WAF/Web应用安全(拦截恶意非法请求)

Web 应用防火墙&#xff08;Web Application Firewall&#xff0c; WAF&#xff09;通过对 HTTP(S) 请求进行检测&#xff0c;识别并阻断 SQL 注入、跨站脚本攻击、跨站请求伪造等攻击&#xff0c;保护 Web 服务安全稳定。 Web 安全是所有互联网应用必须具备的功能&#xff0c…

Linux 下centos 查看 -std 是否支持 C17

实际工作中&#xff0c;可能会遇到c的一些高级特性&#xff0c;例如std::invoke&#xff0c;此函数是c17才引入的&#xff0c;如何判断当前的gcc是否支持c17呢&#xff0c;这里提供两种办法。 1.根据gcc的版本号来推断 gcc --version&#xff0c;可以查看版本号&#xff0c;笔者…

Vue上传图片返回base64并在页面展示,并图片上canvas进行红框框选标记

https://www.cnblogs.com/szqtiger/p/12100754.html vue如何显示base64图片_vue显示base64_不断学习的码农的博客-CSDN博客 图片上进行红框框选_时小帅的博客-CSDN博客 设置canvas画布大小_canvas设置画布大小_最凶残的小海豹的博客-CSDN博客 图片回显 结合以上&#xff0…

Idea maven窗口 展示不分级 maven层级混乱

1. 正在写分布式im 开源项目&#xff1a;nami-im: 分布式im, 集群 zookeeper netty kafka nacos rpc主要为gate&#xff08;长连接服务&#xff09; logic &#xff08;业务&#xff09; lsb &#xff08;负载均衡&#xff09;store&#xff08;存储&#xff09; - Gitee.com …

vue学习笔记(三)

1.vue开发存在SEO问题 前端开发采用vue开发后是单页面 单页面里面&#xff0c;前后端分离&#xff0c;渲染过程是js写的&#xff0c;在js调用接口返回数据之前&#xff0c;页面已经被打开了 实际上就是空白页面&#xff0c;这个时候右键点击查看源代码&#xff0c;实际上是都…

前端学习——Vue (Day2)

指令补充 指令修饰符 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevi…

两天学会用Webpack打包前端代码-day01

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 什么是 Webpack&#xff1f; 使用 Webpack 体验webpack打包过程 修改 Webpack 打包入口和出口 入口 出…

vue3+taro+Nutui 开发小程序(一)

前言&#xff1a;最近在调研开发小程序&#xff0c;发现现在taro框架逐渐成熟&#xff0c;能完美地使用vue3来进行开发&#xff0c;调研中发现京东的Nutui也不错所以准备写一个由0到1的vue3taroNutui的小程序。 这篇我们首先搭建一个框架&#xff1a; vscode插件准备环节&…

Sublime Text 4 激活教程(Windows+Mac)

下载安装 官网 https://www.sublimetext.com 点击跳转 2023.7.21 版本为4143 Windows激活方式 一、激活License方式 入口在菜单栏中"Help” -> “Enter License” 注意格式&#xff0c;可能会过期失效&#xff0c;失效就用方式二 Mifeng User Single User License E…

F.interpolate 数组采样操作

功能&#xff1a;利用插值方法&#xff0c;对输入的张量数组进行上\下采样操作&#xff0c;换句话说就是科学合理地改变数组的尺寸大小&#xff0c;尽量保持数据完整。 在计算机视觉中&#xff0c;interpolate函数常用于图像的放大(即上采样操作)。比如在细粒度识别领域中&…

《Unix环境高级编程》第三版源代码编译

CentOS 7.6 进行编译 使用cat /etc/redhat-release看到操作系统是CentOS Linux release 7.6.1810 (Core)&#xff0c;使用uname -r看到内核是3.10.0-957.el7.x86_64&#xff0c;gcc --version可以看到gcc版本是4.8.5。 wget http://www.apuebook.com/src.3e.tar.gz下载《Uni…

java学习路程之篇一、进阶知识、面向对象高级、static关键字、继承、final关键字、this、super

文章目录 1、面向对象高级2、static关键字3、继承4、final关键字 1、面向对象高级 2、static关键字 3、继承 4、final关键字

MyBatis学习笔记——4

MyBatis学习笔记——4 一、MyBatis的高级映射及延迟加载1.1、多对一1.1.1、第一种方式&#xff1a;级联属性映射1.1.2、第二种方式&#xff1a;association1.1.3、第三种方式&#xff1a;分步查询 1.2、一对多1.2.1、第一种方式&#xff1a;collection1.2.1、第二种方式&#x…

【OAuth2】OAuth2概述及使用GitHub登录第三方网站

【OAuth2】OAuth2概述及使用GitHub登录第三方网站 文章目录 【OAuth2】OAuth2概述及使用GitHub登录第三方网站0. 导言1. OAuth2 简介2. OAuth2 认证授权总体流程3. OAuth2 标准接口4. OAuth2 四种授权模式4.1 授权码模式4.2 简化模式4.3 密码模式4.4 客户端模式 5. GitHub授权登…

Docker 的数据管理、容器互联、镜像创建

目录 一、数据管理 1.数据卷 2. 数据卷容器 二、容器互联&#xff08;使用centos镜像&#xff09; 三、Docker 镜像的创建 1.基于现有镜像创建 1.1首先启动一个镜像&#xff0c;在容器里修改 1.2将修改后的容器提交为新的镜像&#xff0c;需使用该容器的id号创建新镜像 …
最新文章