认证鉴权框架SpringSecurity-1--概念和原理篇
1、基本概念
Spring Security 是一个强大且高度可定制的框架,用于构建安全的 Java 应用程序。它是 Spring 生态系统的一部分,提供了全面的安全解决方案,包括认证、授权、CSRF防护、会话管理等功能。
2、认证、授权和鉴权
(1)、认证
认证是判断一个用户的身份是否合法的过程。用户去访问系统资源时系统要求验证用户的身份信息,身份合法方可继续访问,不合法则拒绝访问。常见的用户身份认证方式有:用户名密码登录,二维码登录,手机短信登录,指纹认证等方式。
(2)、授权
授权是对系统中的用户赋予资源访问权限的过程,通常分为菜单权限,静态资源权限,接口权限等。
(3)、鉴权
授权是用户认证通过后,根据用户的权限来控制用户访问资源的过程,拥有资源的访问权限则正常访问,没有权限则拒绝访问。
3、实现原理
SpringSecurity通过实现一组过滤器来完成安全工作。这些过滤器按顺序处理请求。每个过滤器负责特定的安全任务。这里先简单阐述下主要工作流程,过滤器链在后面会详细描述。
(1)、经典web请求过滤器链
当客户端向服务端发起请求后,容器根据请求 URI 的路径和过滤器相关配置自动创建一个 FilterChain,其中包含过滤器实例和处理 HttpServletRequest 的 Servlet。类似如下图:

当过滤器执行放行后,才会进入到下一个过滤器中,所以调用每个 Filter 的顺序非常重要。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {// 进入servelt前,执行chain.doFilter(request, response); // 执行完servlet后,返回客户端时执行
}
(2)、spring加入过滤器链
当我们使用spring框架时,通过spring也可以加入自定义过滤器,那么spring是怎么做的呢?
答案是:
Spring 提供了一个名为 DelegatingFilterProxy 的过滤器代理类添加到了web请求的过滤器链中(DelegatingFilterProxy 就是一个过滤器)。在这个过滤器中spring做了以下事情:
1、获取到了自身spring容器内的所有Filter的实例(自定义的Filter也是作为Bean被spring容器管理)
2、依次执行了这些过滤器,直到全部执行完成后才放行到web过滤器链中的下一个过滤器或servlet中,这样spring自身的过滤器就都生效了。

DelegatingFilterProxy 代码示例如下:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {// 获取spring容器的所有过滤器BeanFilter delegate = getFilterBean(someBeanName);// 执行过滤器Beandelegate.doFilter(request, response);
}
(3)、springSecurity加入过滤器链
上面我们说了spring通过DelegatingFilterProxy代理过滤器成功加入到web过滤器链中。
springSecurity作为spring家族的一员,自身封装了一组过滤器链的实例(用于认证和授权)。
在DelegatingFilterProxy有一个属性Bean叫FilterChainProxy ,FilterChainProxy 是 Spring Security 提供的一个特殊过滤器,它允许通过 SecurityFilterChain 向多个过滤器实例委托。

FilterChainProxy在DelegatingFilterProxy中封装获取。看下DelegatingFilterProxy源码,如下所示,这里的delegate实际上就是FilterChainProxy对象,
public class DelegatingFilterProxy extends GenericFilterBean {@Nullableprivate String contextAttribute;@Nullableprivate WebApplicationContext webApplicationContext;@Nullableprivate String targetBeanName;private boolean targetFilterLifecycle;@Nullableprivate volatile Filter delegate; // FilterChainProxy就在这里private final Object delegateMonitor;//省略...
}
再看下FilterChainProxy 源码,发现其中就包含一组过滤器链SecurityFilterChain对象。就是这里,springSecurityFilterChain就上场了。
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");private List<SecurityFilterChain> filterChains; // SecurityFilterChain 对象列表//省略...
}

FilterChainProxy 中List 来确定应该为当前请求调用哪一个 SpringSecurityFilterChain 实例。在选择过滤器链时,在FilterChainProxy 中是这样做的:
逻辑:
1、SecurityFilterChain(接口) -> DefaultSecurityFilterChain(实现类),里面有一个getFilters方法,这里就会根据请求返回了一组过滤器 。
2、RequestMatcher接口用来支持匹配HttpServletRequest的策略。匹配策略有很多,此处不多介绍。
3、RequestMatcher -> AntPathRequestMatcher(实现),servlet通过url路径进行匹配 。
private List<Filter> getFilters(HttpServletRequest request) {for (SecurityFilterChain chain : filterChains) {if (chain.matches(request)) { // 根据请求类型选择出不同过滤器链return chain.getFilters();}}return null;}
(4)、异常处理机制
概述:
SpringSecurity的过滤器链中,有一个ExceptionTranslationFilter,这个过滤器会捕获所有与安全相关的异常,并根据异常类型进行相应的处理。常见的安全异常包括:
AuthenticationException:表示认证失败。
AccessDeniedException:表示授权失败,即用户没有权限访问某个资源。
如果是AuthenticationException:
第一步:首先清除 SecurityContextHolder,这个是一个 Spring Security 中的一个核心类。
第二步:RequestCache:保存 HttpServletRequest 请求,在身份验证成功后可以使用它重复原始请求。//也可以不保存,那么用户就需要重新去请求
第三步、AuthenticationEntryPoint 用于从客户端获取请求凭据。// 它可能重定向到登录页面或发送 WWW-Authenticate 报文头。
如果是AccessDeniedException
则拒绝访问。直接调用 AccessDeniedHandler 来处理拒绝访问。// AccessDeniedHandler(接口),也可以自定义处理策略

这里看下ExceptionTranslationFilter的伪代码如下:
如果没有发生任何异常,ExceptionTranslationFilter过滤器直接放行到之后的过滤器;如果发生了安全异常,会根据异常类型走不同的方法,如认证异常(一般重新跳转登录页);如果是权限异常(提示相关的拒绝信息)
try {filterChain.doFilter(request, response);
} catch (AccessDeniedException | AuthenticationException ex) { //捕获特定异常if (!authenticated || ex instanceof AuthenticationException) {startAuthentication(); //启动认证流程} else {accessDenied(); //决绝策略}
}
(5)、原理总结
1、spring通过将DelegatingFilterProxy过滤器链加入到web请求过滤器链中。
2、DelegatingFilterProxy中封装了FilterChainProxy过滤器对象(springSecurity入口)
3、FilterChainProxy中封装了List过滤器链对象。
4、List初始过程会调用getFilters方法获取到目标过滤器链(策略是根据Request对象的URL)
5、之后会遍历执行List过滤器链,执行里面的每一个过滤器,完成认证或授权等过程。
6、如果出现安全异常,ExceptionTranslationFilter中会根据异常的类型走对应的异常处理方法。

学海无涯苦作舟!!!
相关文章:
认证鉴权框架SpringSecurity-1--概念和原理篇
1、基本概念 Spring Security 是一个强大且高度可定制的框架,用于构建安全的 Java 应用程序。它是 Spring 生态系统的一部分,提供了全面的安全解决方案,包括认证、授权、CSRF防护、会话管理等功能。 2、认证、授权和鉴权 (1&am…...
计算器上的MC、MR、M+、M—、CE是什么意思?
在计算器中, MC键叫做memory clear,中文 清除存储,是一个清除寄存器中存储数字的指令。 MS键叫做memory save,中文 存入存储。 而MR键,则是一个读取原先存储在寄存器中的数字的指令。 M键指将当前数值存入寄存器以…...
无人机飞手执照处处需要,森林、石油管道、电力巡检等各行业都需要
无人机飞手执照在多个行业中确实具有广泛的应用需求,包括森林、石油管道、电力巡检等领域。以下是对这些领域无人机飞手执照需求的具体分析: 一、森林领域 在森林领域,无人机飞手执照对于进行高效、准确的森林资源管理和监测至关重要。无人机…...
计算机网络——路由选择算法
路由算法 路由的计算都是以子网为单位计算的——找到从原子网到目标子网的路径 链路状态算法...
【前端】技术演进发展简史
一、前端 1、概述 1990 年,第一个web浏览器诞生,Tim 以超文本语言 HTML 为基础在 NeXT 电脑上发明了最原始的 Web 浏览器。 1991 年,WWW诞生,这标志着前端技术的开始。 前端(Front-end)和后端(…...
深入解析贪心算法及其应用实例
标题:深入解析贪心算法及其应用实例 一、引言 贪心算法(Greedy Algorithm)是一类简单、直观的算法设计策略,广泛应用于优化问题中。其基本思想是每一步都选择当前状态下最优的选择,即在每一步做出局部最优的决策&…...
电子工牌独立双通道定向拾音方案(有视频演示)
现在一些行业的客服人员在面对客户都要求使用电子工牌分别记录客服和顾客的声音,我们利用双麦克风阵列双波束拾音的方案设计了一个电子工牌方案.可以有效分别记录客服和顾客的声音. 方案思路: 我们采用了一个双麦阵列波束拾音的模块A-59,此模块可以利用2个麦克风组成阵列进行双…...
举例理解LSM-Tree,LSM-Tree和B+Tree的比较
写操作 write1:WAL 把操作同步到磁盘中WAL做备份(追加写、性能极高) write2:Memtable 完成WAL后将(k,v)数据写入内存中的Memtable,Memtable的数据结构一般是跳表或者红黑树 内存内采用这种数据结构一方面支持内存…...
React Native 全栈开发实战班 - 核心组件与导航
在 React Native 中,组件是构建用户界面的基本单元。React Native 提供了丰富的内置组件,涵盖了从基础布局到复杂交互的各种需求。本章节将详细介绍常用的内置组件,并重点讲解列表与滚动视图的使用。 1. 常用内置组件详解 React Native 提供…...
Leecode热题100-35.搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 示例 1: 输入: nums [1,3,5,6], target 5 输出: 2示例 2: 输入:…...
密码学知识点整理二:常见的加密算法
常用的加密算法包括对称加密算法、非对称加密算法和散列算法。 对称加密算法 AES:高级加密标准,是目前使用最广泛的对称加密算法之一,支持多种密钥长度(128位、192位、256位),安全性高,加密效率…...
Linux如何将文件或目录打成rpm包?-- rpmbuild打包详解
👨🎓博主简介 🏅CSDN博客专家 🏅云计算领域优质创作者 🏅华为云开发者社区专家博主 🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入!…...
RabbitMQ-死信队列(golang)
1、概念 死信(Dead Letter),字面上可以理解为未被消费者成功消费的信息,正常来说,生产者将消息放入到队列中,消费者从队列获取消息,并进行处理,但是由于某种原因,队列中的…...
爬虫开发工具与环境搭建——环境配置
第二章:爬虫开发工具与环境搭建 第二节:环境配置 在进行爬虫开发之前,首先需要配置好开发环境。一个良好的开发环境不仅能提高开发效率,还能避免因环境不一致带来的问题。以下是环境配置的详细步骤,涵盖了Python开发…...
15.UE5等级、经验、血条,魔法恢复和消耗制作
2-17 等级、经验、血条、魔法消耗_哔哩哔哩_bilibili 目录 1.制作UI,等级,经验,血条 2.为属性面板绑定角色真实的属性,实现动态更新 3.魔法的消耗和恢复 1.制作UI,等级,经验,血条 创建控…...
【Homework】【5】Learning resources for DQ Robotics in MATLAB
Lesson 5 代码-TwoDofPlanarRobot.m 表示一个 2 自由度平面机器人。该类包含构造函数、计算正向运动学模型的函数、计算平移雅可比矩阵的函数,以及在二维空间中绘制机器人的函数。 classdef TwoDofPlanarRobot%TwoDofPlanarRobot - 表示一个 2 自由度平面机器人类…...
vue3中 ref和reactive的区别
ref的主要作用 ref 函数接受的参数数据类型可以是原始数据类型也可以是引用数据类型。在模板中使用 ref 时,我们不需要加 .value,因为当 ref 在模板中作为顶层属性被访问时,它们会被自动解包, <p>count: {{ count }}</…...
第十四章 Spring之假如让你来写AOP——雏形篇
Spring源码阅读目录 第一部分——IOC篇 第一章 Spring之最熟悉的陌生人——IOC 第二章 Spring之假如让你来写IOC容器——加载资源篇 第三章 Spring之假如让你来写IOC容器——解析配置文件篇 第四章 Spring之假如让你来写IOC容器——XML配置文件篇 第五章 Spring之假如让你来写…...
群控系统服务端开发模式-应用开发-前端个人资料开发
一、总结 其实程序开发到现在,简单的后端框架就只剩下获取登录账号信息及获取登录账号菜单这两个功能咯。详细见下图: 1、未登录时总业务流程图 2、登录后总业务流程图 二、获取登录账号信息对接 在根目录下src文件夹下store文件夹下modules文件夹下的us…...
动态规划技巧点
动规五部曲(来自b站卡哥):1、确定DP数组中i、j…的含义。2、确定DP推导式。3、DP数组初始化。4、DP数组遍历顺序。5、DP数组打印校验。 父问题、子问题有些许区别:LeetCode343.整数拆分 今天在哔哩哔哩上刷到了一个非常有意思的l…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
消息队列系统设计与实践全解析
文章目录 🚀 消息队列系统设计与实践全解析🔍 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡💡 权衡决策框架 1.3 运维复杂度评估🔧 运维成本降低策略 🏗️ 二、典型架构设计2.1 分布式事务最终一致…...
LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)
在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...
JS红宝书笔记 - 3.3 变量
要定义变量,可以使用var操作符,后跟变量名 ES实现变量初始化,因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符,可以创建一个全局变量 如果需要定义…...
文件上传漏洞防御全攻略
要全面防范文件上传漏洞,需构建多层防御体系,结合技术验证、存储隔离与权限控制: 🔒 一、基础防护层 前端校验(仅辅助) 通过JavaScript限制文件后缀名(白名单)和大小,提…...
跨平台商品数据接口的标准化与规范化发展路径:淘宝京东拼多多的最新实践
在电商行业蓬勃发展的当下,多平台运营已成为众多商家的必然选择。然而,不同电商平台在商品数据接口方面存在差异,导致商家在跨平台运营时面临诸多挑战,如数据对接困难、运营效率低下、用户体验不一致等。跨平台商品数据接口的标准…...
计算机系统结构复习-名词解释2
1.定向:在某条指令产生计算结果之前,其他指令并不真正立即需要该计算结果,如果能够将该计算结果从其产生的地方直接送到其他指令中需要它的地方,那么就可以避免停顿。 2.多级存储层次:由若干个采用不同实现技术的存储…...
