SpringSecurity安全过滤器工作原理

前面通过三篇文章,从底层代码的角度分析了SpringSecurity的初始化过程。

接下来我们就要具体看一下,Spring Security的安全过滤器初始化、装配好之后,到底是怎么工作的。

还是按图索骥


 

下面我们简单从底层源码分析一下,请求是怎么调用到Spring Security的安全过滤器的。
#### Spring Security安全过滤器工作原理
前面文章已经分析过DelegatinFilterProxy调用到FilterChainProxy的源码,所以我们今天直接从FilterChainProxy的doFilter方法开始:
```
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        boolean clearContext = request.getAttribute(FILTER_APPLIED) == null;
        if (!clearContext) {
            doFilterInternal(request, response, chain);
            return;
        }
        try {
            request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
            doFilterInternal(request, response, chain);
        }
        catch (RequestRejectedException ex) {
            this.requestRejectedHandler.handle((HttpServletRequest) request, (HttpServletResponse) response, ex);
        }
        finally {
            SecurityContextHolder.clearContext();
            request.removeAttribute(FILTER_APPLIED);
        }
    }
```

直接看doInternalFilter方法。首先调用getFilters方法:
```
private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        FirewalledRequest firewallRequest = this.firewall.getFirewalledRequest((HttpServletRequest) request);
        HttpServletResponse firewallResponse = this.firewall.getFirewalledResponse((HttpServletResponse) response);
        List<Filter> filters = getFilters(firewallRequest);
        //省略部分源码
        VirtualFilterChain virtualFilterChain = new VirtualFilterChain(firewallRequest, chain, filters);
        virtualFilterChain.doFilter(firewallRequest, firewallResponse);
    }
```
这个getFilters方法的源码就不贴出了,有兴趣的童鞋打开源码看一下,非常简单:从FilterChainProxy持有的DefaultSecurityFilterChain对象中获取到filters,这个filters就是Spring Security初始化过程中装配好的Spring Security的各安全过滤器。

之后用安全过滤器组装一个叫virtualFilterChain的内部对象,这个内部对象主要就是为了持有Spring Security的安全过滤器的,然后通过调用virtualFilterChain的doFilter方法,逐个调用Spring Security的安全过滤器。
#### Spring Security安全过滤器
Spring Security有不少安全过滤器(下图,SprigBoot默认启动的就有15个),我们主要关注与用户身份认证及鉴权密切相关的、或者项目中比较常见的过滤器,其他过滤器暂时略过或一笔带过。
![image.png](/img/bVc4txS)

#### 1.WebAsyncManagerIntegrationFilter
web异步集成过滤器,创建SecurityContextCallableProcessingInterceptor并注册到WebAsyncManager中。

详细作用略。

#### 2.SecurityContextPersistenceFilter
将包含认证信息的SecurityContextHolder在认证之后保存起来(保存在SecurityContextRepository中,一般情况下是session),并且在每次请求发起、认证发生之前从SecurityContextRepository获取出来放置到SecurityContextHolder中。

SecurityContextPersistenceFilter是Spring Security的第2个安全过滤器,在所有认证过滤器之前执行。

SecurityContextPersistenceFilter首先从session中(默认情况下)获取SecurityContext,如果session中没有SecurityContext则创建一个空的SecurityContext,之后将SecurityContext存入SecurityContextHolder。

默认情况下SecurityContextHolder通过ThreadLocalSecurityContextHolderStrategy(也就是使用ThreadLocal)存储SecurityContext。

最后,在请求执行完成之后,将SecurityContextHolder持有的SecurityContext保存起来(默认存储在session中),并清空SecurityContextHolder。

***这样,通过SecurityContextPersistenceFilter过滤器,Spring Security就可以在其他安全过滤器执行之前,从session中获取当前用户的认证信息,因而在后续用户认证操作执行之前、如果当前用户已经完成了认证、则可以确保能够获取到当前用户的认证信息,因此能够通过后续的用户认证过程!!!***

#### 3.HeaderWirterFilter
写Response头信息以便达到对Http Response的相应控制。

HeaderWirterFilter初始化的时候会注册如下HeadWriter:
![image.png](/img/bVc4MXi)
这些HeadWriter会帮助我们对Http Response Header做一些默认设置,比如CacheControlHeadersWriter会执行如下操作:

```
    private static List<Header> createHeaders() {
        List<Header> headers = new ArrayList<>(3);
        headers.add(new Header(CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate"));
        headers.add(new Header(PRAGMA, "no-cache"));
        headers.add(new Header(EXPIRES, "0"));
        return headers;
    }
```
一般情况下,我们的应用需要这样的设置,不使用Spring Security的话我们的应用需要手动设置,使用了Spring Security的话,就不需要多此一举了。

#### 4.CsrfFilter
跨域请求过滤器,主要作用是防跨域攻击。

#### 5.LogoutFilter
处理Logout请求,并导航到logout页面。

#### 6.UsernamePasswordAuthenticationFilter
这是Spring Security用户认证的默认实现。

![image.png](/img/bVc4S1M)

他有一个叫AbstractAuthenticationProcessingFilter的父类,doFilter方法就是在父类实现的。

只针对post方法的/login请求生效,所以如果我们要使用该过滤器的话,应用的登录必须是post方法的/login请求。

Spring Security的登录认证过程就是通过这个过滤器实现的,相对还比较复杂,篇幅关系今天就不展开了,今天的主要目标是要搞清楚他的作用。

首先验证当前请求是否需要登录认证,如前所述,如果请求不是post的/login的话,则不做登录认证。

从request中获取的username,password创建UsernamePasswordAuthenticationToken对象进行认证。

认证的过程其实就是我们验证用户名、密码的过程,SpringSecurity有一个默认的用户名、密码认证实现,是在系统启动过程中为用户user生成UUID并打印在控制台、通过用户名user、密码为该UUID完成认证。我们可以实现自己的认证,比如通过数据库的用户名、密码方式完成认证。

认证通过则将认证信息存储在SecurityContext中,如果认证失败(比如用户名密码错误等)则清空SecurityContext并记录相关异常。

#### 7.DefaultLoginPageGeneratingFilter
为/login请求生成登录页面。

#### 8.DefaultLogoutPageGeneratingFilter
导航到登出页面。

#### 9.BasicAuthenticationFilter
对于采用Basic Authentication的请求执行认证。Basi Authentication指的是请求头中包含:
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

其中Basic后是采用base64编码的密码信息。

不太了解、没有使用过这种认证方式,略过。

#### 10.RequestCacheAwareFilter
主要作用是缓存当前请求信息,以便在由于认证未通过无法执行该请求的情况下,后续认证通过后重新发起该请求。

#### 11.SecurityContextHolderAwareRequestFilter
用于对request做一层包装,以便支持Servlet中安全相关的API调用。

#### 12.AnonymousAuthenticationFilter
匿名过滤器,从SecurityContextHolder获取认证信息,如果经过了前面的SecurityContextPersistenceFilter、以及UsernamePasswordAuthenticationFilter处理后,SecurityContextHolder中还是没有认证信息的话,说明当前请求并没有通过Spring Security的安全认证,则创建一个匿名认证信息存储在SecurityContextHolder中。

#### 13.SessionManagementFilter
session管理的过滤器,主要为了防止session固化攻击、以及实现登录并发控制功能。

#### 14.ExceptionTranslationFilter
实现异常控制的安全过滤器,注意该过滤器对异常的处理是安全过滤器链执行完成、返回之后。所以,下面的第14个、第15个过滤器执行过程中的异常,也能被本过滤器捕获并处理。

主要处理Spring Security的两类异常:
1. AuthenticationException
2. AccessDeniedException
并将异常交给相应的异常处理器进行处理,比如AccessDeniedException异常处理器通常会通过response返回前端403错误。

#### 15.FilterSecurityInterceptor
Spring Security主要安全过滤器的执行已经接近尾声,但是这个FilterSecurityInterceptor是重头戏。

FilterSecurityInterceptor主要完成如下工作:
1. 解析当前请求的安全配置,主要包括:permitAll、authenticated、denyAll、anonymous等。
2. 从SecurityContextHolder获取安全认证信息。
3. 根据当前请求的安全配置信息及当前用户的安全认证信息进行认证投票,其实就是判断获取到的当前用户的安全认证信息是否符合配置的安全认证需求,符合的话则通过认证,不符合的话抛出accesssdeny异常。

之所以说FilterSecurityInterceptor是Spring Security安全过滤器的重头戏,是因为我们根据项目的具体需求、针对不同请求配置好的安全认证标准的解析是FilterSecurityInterceptor完成的,解析之后检查当前用户是否满足请求所需要的安全要求也是FilterSecurityInterceptor完成的。

如果当前用户认证信息不满足当前请求的安全需求,比如匿名用户访问/helloworld、/helloworld配置为authenticated的话,FilterSecurityInterceptor会抛出accesssdeny异常,最终经ExceptionTranslationFilter处理之后前台页面会收到403错误信息。

#### 总结

Spring security主要安全过滤器的基本工作原理分析完毕,其实每一个安全过滤器的底层工作细节都可以单独写一篇文章进行代码级的分析。但是一般来讲,对于相对复杂一点的知识,入门学习的时候太过细节的分析会影响到对整体框架的理解,Spring Security相对来讲比较负责,因此适合这一原则。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/weixin_44612246/article/details/128357129

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

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

相关文章

赋能业务全球化,明道云HAP通过亚马逊云科技 FTR认证

近日&#xff0c;明道云作为融合多元能力的超级应用平台&#xff0c;成功通过了AWS&#xff08;Amazon Web Service&#xff09;的FTR&#xff08;Foundational Technical Review&#xff09;认证。FTR是亚马逊云科技为合作伙伴解决方案提供的一项全面技术审核机制&#xff0c;…

Verilog代码bug:一种特殊的组合逻辑环

Verilog代码bug&#xff1a;一种特殊的组合逻辑环 组合逻辑环&#xff08;Combinational Loop&#xff09;是什么&#xff0c;别的文章已经写的很多了&#xff0c;本文就不赘述了&#xff0c;本文主要记录遇到过的一种特殊的逻辑环&#xff1b; 代码如下所示&#xff1a; mo…

苹果电脑卡顿反应慢怎么办 苹果电脑卡顿严重解决方法 mac电脑太卡了怎么办

作为Mac用户&#xff0c;你是否正在经历或者曾经遭遇过电脑卡顿、反应慢的困扰&#xff1f;这可能是由于多种原因导致的&#xff0c;包括自启动程序过多、系统与应用未及时更新、内存管理不当等。今天和你一起来探讨下&#xff0c;苹果电脑卡顿反应慢时怎么办。希望能够帮助你解…

知乎广告推广投放流程以及价格?

知乎作为一个拥有庞大高质量用户群体的知识分享平台&#xff0c;成为了众多品牌不可忽视的广告投放渠道。知乎不仅汇聚了各行各业的专业人士&#xff0c;其独特的社区氛围也为品牌提供了精准触达目标受众的机会。知乎广告推广的投放流程、费用标准&#xff0c;云衔科技提供的专…

css如何实现边框模糊的效果

其实并不难&#xff0c;用属性 filter: blur(数字px); 即可。效果如下&#xff1a; 图上的圆形内有色彩的渐变&#xff0c;同样也是用filter: blur(数字px); 实现的&#xff0c;代码如下&#xff1a;、 <template><div id"root" :style"{}">…

Jenkins构建流程

Jenkins是DevOps【(Development和Operations的混成词&#xff09;是一种重视“软件开发人员&#xff08;Dev&#xff09;”和“IT运维技术人员&#xff08;Ops&#xff09;”之间沟通合作的文化、运动或惯例)】的重要一环&#xff0c;是一款开源的CI&CD软件。也就是持续集成…

【35分钟掌握金融风控策略27】贷中风控策略与客户运营体系

目录 贷中风控策略与客户运营体系 贷中风控日标 贷中风控数据源 贷中风控策略与客户运营体系 贷中是风控的第二道防线&#xff0c;贷中阶段风控的重点工作就是存量客户风控及运营。在当下&#xff0c;新客市场趋于饱和且获客成本越来越高&#xff0c;所以&#xff0c;在做好…

手撸XXL-JOB(四)——远程调用定时任务

Java Socket网络编程 网络编程是Java编程中的重要组成部分&#xff0c;包括服务端和客户端两部分内容。Socket是Java网络编程的基本组件之一&#xff0c;用于在应用程序之间提供双向通信&#xff0c;Socket提供了一种标准的接口&#xff0c;允许应用程序通过网络发送和接收数据…

车载GPT爆红前夜:一场巨头竞逐的游戏

在基于GPT-3.5的ChatGPT问世之前&#xff0c;OpenAI作为深度学习领域并不大为人所看好的技术分支玩家&#xff0c;已经在GPT这个赛道默默耕耘了七八年的时间。 好几年的时间里&#xff0c;GPT始终没有跨越从“不能用”到“能用”的奇点。转折点发生在2020年6月份发布的GPT-3&a…

实时“秒回”,像真人一样语音聊天,GPT-4o模型强到恐怖

今天凌晨OpenAl发布了 GPT-4o&#xff0c;这是一种新的人工智能模式&#xff0c;集合了文本、图片、视频、语音的全能模型。 能实时响应用户的需求&#xff0c;并通过语音来实时回答你&#xff0c;你可以随时打断它。还具有视觉能力&#xff0c;能识别物体并根据视觉做出快速的…

Fabric实现多GPU运行

官方的将pytorch转换为fabric简单分为五个步骤&#xff1a; 步骤 1&#xff1a; 在训练代码的开头创建 Fabric 对象 from lightning.fabric import Fabricfabric Fabric() 步骤 2&#xff1a; 如果打算使用多个设备&#xff08;例如多 GPU&#xff09;&#xff0c;就调用…

gin导出excel文件

go可以通过excelize 包实现对excel的操作 "github.com/xuri/excelize/v2"导出示例 service层 批量导出数据的&#xff0c;我们可以在dao层中返回一个切片。在service中新建一个excelize对象&#xff0c;单独设置表头。遍历切片往excelize上修改即可。 func (s *S…

05-13 周一 量化是什么

05-13 周一 量化是什么 时间版本修改人描述2024年5月13日11:27:25V0.1宋全恒新建文档2024年5月14日16:21:20V1.0宋全恒了解 简介 神经网络在运行时有较高的计算成本&#xff0c;而且随着大模型时代的到来&#xff0c;知识由一个巨大的LLM存储&#xff0c;为了获取知识&#xf…

【STM32】状态机实现定时器按键消抖,处理单击、双击、三击、长按事件

目录 一、简单介绍 二、模块与接线 三、cubemx配置 四、驱动编写 状态图 按键类型定义 参数初始化/复位 按键扫描 串口重定向 主函数 五、效果展示 六、驱动附录 key.c key.h 一、简单介绍 众所周知&#xff0c;普通的机械按键会产生抖动&#xff0c;可以采取硬件…

【江南大学×朗汀留学】部分留学录取案例合集

朗汀留学 X 江南大学 尽管客观条件如此艰难&#xff0c;朗汀留学的同学们还是斩获众多名校的录取。成绩属于过去&#xff0c;我们继续努力创造更好未来。 以下为我们摘取的江南大学部分学生案例供大家参考&#xff0c;再次恭喜所有获得理想大学offer的学生们&#xff0c;你们…

CAST: Cross-Attention in Space and Time for Video Action Recognition

标题&#xff1a;CAST: 时空交叉注意力网络用于视频动作识别 原文链接&#xff1a;2311.18825v1 (arxiv.org)https://arxiv.org/pdf/2311.18825v1 源码链接&#xff1a;GitHub - KHU-VLL/CASThttps://github.com/KHU-VLL/CAST 发表&#xff1a;NeurIPS-2023&#xff08;CCF A…

Linux第四节--常见的指令介绍集合(持续更新中)

点赞关注不迷路&#xff01;本节涉及初识Linux第四节&#xff0c;主要为常见的几条指令介绍。 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1f44d;&#x1f3fb; 收藏 ✨ 加关注&#x1f440; 期待与你共同进步! 1. more指令 语法&#xff1a;more [选项][文件]…

MySQL文档_下载

可能需要&#xff1a;MySQL下载–》更新版本–》迁移数据库到MySQL 以下都不重要【只要确定好需要安装版本&#xff0c;找到对应的版本下载&#xff0c;安装&#xff0c;设置即可】 下载、安装&#xff1a; Determine whether MySQL runs and is supported on your platform…

电脑刚开机的时候不卡,用一会就变卡顿了…怎么回事?

前言 昨天咱们聊到旧电脑更换了固态硬盘之后&#xff0c;开机就会变快的事情&#xff0c;这个确实是可行且有效的升级电脑办法之一。 看完这篇之后&#xff0c;切莫着急升级电脑硬件配置&#xff0c;因为这里的坑比你想象的还要多。 从机械硬盘测试的数据和固态硬盘的测试数…

【C语言】—— 动态内存管理

【C语言】——动态内存管理 一、动态内存管理概述1.1、动态内存的概念1.2、动态内存的必要性 二、 m a l l o c malloc malloc 函数2.1、函数介绍2.2、应用举例 三、 c a l l o c calloc calloc 函数四、 f r e e free free 函数4.1、函数介绍4.2、应用举例 五、 r e a l l o …