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

news2024/11/23 15:34:17

目录

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.coloradmin.cn/o/777603.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解锁潜力,驭数赋能:大数据与云计算的强强联合

随着数字化时代的来临&#xff0c;大数据和云计算已成为信息技术领域的两大热门话题。大数据指的是以海量、高速、多样化的数据为基础&#xff0c;通过分析和挖掘来获得有价值的信息和洞察。而云计算则是一种基于网络的计算模式&#xff0c;通过将数据和应用程序存储在云端服务…

day31-Password Generator(密码生成器)

50 天学习 50 个项目 - HTMLCSS and JavaScript day31-Password Generator&#xff08;密码生成器&#xff09; 效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport&q…

Qt 之 自定义日志文件,QtMessageHandler应用

目录 一、前言 二、头文件代码 三、源文件代码 四、使用示例 五、使用效果 一、前言 在qt程序发布后&#xff0c;还需要查看一些调试输出信息&#xff0c;一般将输出信息写入日志文件&#xff0c;本文通过自定义函数实现将Debug、Warning、Critical、Fatal及Info信息自动输…

品牌全量数据监测分析

线上渠道众多&#xff0c;涉及的产品链接量也是巨大的&#xff0c;多数品牌在做线上数据监测时&#xff0c;是需要对全量数据进行监测分析&#xff0c;比如对某个SKU的全量数据&#xff0c;或者对某个竞品的全量数据进行监测&#xff0c;所以需求确认了&#xff0c;是否有能做到…

windows系统安装指定的vue/cli、node和npm;vue/cli脚手架搭建项目所涉及的vue/cli、node、npm依赖版本等问题

文章目录 前言一、安装vue/cli脚手架1.安装指定版本脚手架&#xff0c;我是用的3.12.0版本2.查看版本是否安装成功&#xff0c;成功有版本号2.1问题&#xff1a;安装失败2.2解决方案2.3 安装成功 二、安装指定node和npm1.为什么需要安装指定node和npm版本&#xff0c;同时匹配v…

【mysql】—— 表的操作

前言&#xff1a; 在上期中&#xff0c;我们把 mysql 中库的基本操作进行了相应的讲解。本期&#xff0c;我将给大家讲解的是关于mysql 中表的基本操作。 目录 &#xff08;一&#xff09;创建表 &#xff08;二&#xff09;查看表结构 1、DESCRIBE 方式 2、SHOW CREATE TA…

Data Structure, Algorithm,and Applications in C++

在学习这本书进阶内容之前&#xff0c;我们可以跟着它的第一章部分再巩固和复习。本书由Sartaj Sahni撰写&#xff0c;由王立柱和刘志红翻译。全书通俗易懂&#xff0c;内容丰富&#xff0c;是巩固C内容的不二选择。希望本文对各位有所帮助。 目录 1.函数与参数 1.1.传值参数…

【备考2023年CISSP认证考试学习手册,信息系统安全在职人员日常参考指南——《CISSP信息系统安全专家认证All-in-One(第9版)》】

《CISSP信息系统安全专家认证All-in-One(第9版)》针对最新发布的CISSP考试做了全面细致的修订和更新&#xff0c;涵盖(ISC)2新开发的2021 CISSP考试大纲的所有目标。这本综合性权威指南编排精当&#xff0c;每章开头列出学习目标&#xff0c;正文中穿插考试提示&#xff0c;章末…

精准测试之分布式调用链底层逻辑

目录 前言&#xff1a; ⼀、分布式调⽤链系统概述 分布式架构所带来的问题 分布式链路监控的作用 ⼆、调用链系统的演进 链路监控系统列表 三、调用链系统的底层实现逻辑 调用链系统的本质 调用链基本元素 事件捕捉 事件串联 事件的开始与结束 上传 四、Span 内容…

抖音账号矩阵系统源码解析和实现技巧。

开发背景 抖音是目前非常火爆的一款短视频社交软件&#xff0c;拥有数亿用户&#xff0c;每天都有大量的视频上传和分享。如何有效地管理和运营这些用户账号成为了各大抖音号主的一个难题。而抖音账号矩阵系统源码解析和实现技巧则成为了越来越多人关注的话题。 首先&#xf…

python用selenium模拟谷歌浏览器点页面

1、cmd安装selenium&#xff0c;输入pip install selenium 2、模拟点击热搜第一条进去&#xff0c;连接如下 https://weibo.com/newlogin?tabtypeweibo&gid102803&openLoginLayer0&urlhttps%3A%2F%2Fweibo.com%2F 3、查看谷歌版本 4、并去下面下载对应版本的web…

分布式光伏电站监控及集中运维管理-安科瑞黄安南

前言&#xff1a;今年以来&#xff0c;在政策利好推动下光伏、风力发电、电化学储能及抽水蓄能等新能源行业发展迅速&#xff0c;装机容量均大幅度增长&#xff0c;新能源发电已经成为新型电力系统重要的组成部分&#xff0c;同时这也导致新型电力系统比传统的电力系统更为复杂…

mac系统占用100多G怎么清除 mac内存系统占用了好多怎么清理

mac电脑运行速度足以傲视其他电脑系统&#xff0c;不易卡顿死机是苹果电脑的优势&#xff0c;但是其偏小的存储空间令人十分头痛。如果你的mac磁盘容量是仅有12GB&#xff0c;在使用一段时间之后&#xff0c;系统内存很有可能就要占用100多G&#xff0c;很快电脑会出现空间不够…

前端学习——ajax (Day2)

案例 - 图书管理 Bootstrap 弹框 modal官方文档 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport"…

小程序分类如何移动顺序

小程序的分类排序功能可以帮助商家根据自己的需求来调整展示在前端页面上的分类顺序&#xff0c;以便更好地呈现商品和提升用户体验。下面将介绍如何在小程序中进行分类移动顺序的操作步骤。 在小程序管理员后台->分类管理&#xff0c;可以看到所有的分类。 向上移动分类&a…

基于Go/Grpc/kubernetes/Istio开发微服务的最佳实践尝试

Jgrpc 本项目为基于 Go/Grpc/kubernetes/Istio 开发微服务的最佳实践提供参考。 并基于 Jenkins/Gitlab/Harbor 实现了CICD。 并使用 grpc-gateway 作为网关代理。 本最佳实践分为三个部分&#xff1a; 创建一个 pingservice 的微服务创建一个 pongservice 的微服务基于Je…

万宾管网水质监测仪 | 守护城市水生态环境

WITBEE万宾 管网水质监测仪EN400-WQ&#xff0c;新一代城市生命线智能监测仪器&#xff0c;可选 COD、氨氮和电导率等7项组合监测指标&#xff0c;4G无线通信适应地下排水管网极端恶劣环境&#xff0c;3年自供电长续航&#xff01;

【远程访问】文件同步工具:本地搭建免费开源的Syncthing自动文件同步服务器

文章目录 1.前言2. Syncthing网站搭建2.1. Syncthing下载和安装2.2. Syncthing网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 在数据爆炸的当下&#xff0c;每天都会产生海量的数据&#xff0c;这些数据可…

手劈二叉树

二叉树 概念 二叉树是一种常见的树状数据结构&#xff0c;每个节点最多有两个子节点&#xff0c;称为左子节点 和右子节点。它可以为空树&#xff08;没有任何节点&#xff09;&#xff0c;或者由根节点及其子节点组成。特点 具有层级结构&#xff0c;其中顶层的节点被称为根…

请求头/响应头、POST的使用方法、常用协议状态码

POST请求方法&#xff1a;添加资源 常用的几种数据格式&#xff1a; 1、XML的格式 2、表单数据格式 3、JSON数据格式 请求地址 请求方法 请求头 请求参数 COOKI E&#xff1a; 1、反爬虫 2、身份认证 Referer:请求是从哪个页面发送过来的 User-Agent&#xff1a;通…