SpringSecurity(11)——核心组件和认证流程

获取用户信息

// 获取安全上下文对象,就是那个保存在 ThreadLocal 里面的安全上下文对象
// 总是不为null(如果不存在,则创建一个authentication属性为null的empty安全上下文对象)
SecurityContext securityContext = SecurityContextHolder.getContext();// 获取当前认证了的 principal(当事人),或者 request token (令牌)
// 如果没有认证,会是 null,该例子是认证之后的情况
Authentication authentication = securityContext.getAuthentication()// 获取当事人信息对象,返回结果是 Object 类型,但实际上可以是应用程序自定义的带有更多应用相关信息的某个类型。
// 很多情况下,该对象是 Spring Security 核心接口 UserDetails 的一个实现类,你可以把 UserDetails 想像
// 成我们数据库中保存的一个用户信息到 SecurityContextHolder 中 Spring Security 需要的用户信息格式的
// 一个适配器。
Object principal = authentication.getPrincipal();
if (principal instanceof UserDetails) {String username = ((UserDetails)principal).getUsername();
} else {String username = principal.toString();
}

SecurityContextHolder

SecurityContextHolder持有的是安全上下文的信息,当前操作的用户是谁,用户是否已经被认证,他拥有哪些角色权限等,这些都被保存在SecurityContextHolder中。SecurityContextHolder默认使用ThreadLocal策略来存储认证信息,在web环境下,SpringSecurity在用户登录时自动绑定认证信息到当前线程,在用户退出时,自动清除当前线程的认证信息

public class SecurityContextHolder {// 三种工作模式的定义,每种工作模式对应一种策略public static final String MODE_THREADLOCAL = "MODE_THREADLOCAL";public static final String MODE_INHERITABLETHREADLOCAL = "MODE_INHERITABLETHREADLOCAL";public static final String MODE_GLOBAL = "MODE_GLOBAL";// 类加载时首先尝试从环境属性中获取所指定的工作模式public static final String SYSTEM_PROPERTY = "spring.security.strategy";	private static String strategyName = System.getProperty(SYSTEM_PROPERTY);private static SecurityContextHolderStrategy strategy;// 初始化计数器,初始为0,// 1. 类加载过程中会被初始化一次,此值变为1// 2. 此后每次调用 setStrategyName 会对新的策略对象执行一次初始化,相应的该值会增1private static int initializeCount = 0;static {initialize();}/*** 清除上下文*/public static void clearContext() {strategy.clearContext();}/*** 获取上下文*/public static SecurityContext getContext() {return strategy.getContext();}/*** 获取计数器的值*/public static int getInitializeCount() {return initializeCount;}private static void initialize() {if (!StringUtils.hasText(strategyName)) {// Set default, 设置缺省工作模式/策略 MODE_THREADLOCALstrategyName = MODE_THREADLOCAL;}if (strategyName.equals(MODE_THREADLOCAL)) {strategy = new ThreadLocalSecurityContextHolderStrategy();} else if (strategyName.equals(MODE_INHERITABLETHREADLOCAL)) {strategy = new InheritableThreadLocalSecurityContextHolderStrategy();} else if (strategyName.equals(MODE_GLOBAL)) {strategy = new GlobalSecurityContextHolderStrategy();} else {// Try to load a custom strategytry {Class<?> clazz = Class.forName(strategyName);Constructor<?> customStrategy = clazz.getConstructor();strategy = (SecurityContextHolderStrategy) customStrategy.newInstance();}catch (Exception ex) {ReflectionUtils.handleReflectionException(ex);}}initializeCount++;}/*** 设置上下文*/public static void setContext(SecurityContext context) {strategy.setContext(context);}/*** 设置工作模式*/public static void setStrategyName(String strategyName) {SecurityContextHolder.strategyName = strategyName;initialize();}/*** 获取对应工作模式的策略*/public static SecurityContextHolderStrategy getContextHolderStrategy() {return strategy;}/*** 创建空的上下文信息*/public static SecurityContext createEmptyContext() {return strategy.createEmptyContext();}public String toString() {return "SecurityContextHolder[strategy='" + strategyName + "'; initializeCount="+ initializeCount + "]";}
}

SecurityContext

安全上下文,主要持有Authentication对象,如果用户未鉴权,那么Authentication对象将会是空的

public interface SecurityContext extends Serializable {/*** 获取当前经过身份验证的主体,或身份验证请求令牌*/Authentication getAuthentication();/*** 更改当前经过身份验证的主体,或删除身份验证信息*/void setAuthentication(Authentication authentication);
}

Authentication

鉴权对象,该对象主要包含了用户的详细信息(UserDetails)和用户鉴权所需要的信息,如用户提交的用户名密码、Remember-me Token或digest hash值等,按不同鉴权方式使用不同的Authentication实现

public interface Authentication extends Principal, Serializable {//用来获取用户的权限。Collection<? extends GrantedAuthority> getAuthorities();//用来获取用户凭证,一般来说就是密码。Object getCredentials();//用来获取用户携带的详细信息,可能是当前请求之类的东西。Object getDetails();//用来获取当前用户,可能是一个用户名,也可能是一个用户对象。Object getPrincipal();//判断当前用户是否认证成功。boolean isAuthenticated();//设置用户是否认证成功void setAuthenticated(boolean var1) throws IllegalArgumentException;
}

GrantedAuthority

表示了当前用户所拥有的权限(或角色)信息,这些信息由授权负责对象AccessDecisionManager来使用,并决定最终用户是否可以访问某资源(URL或方法调用或域对象),鉴权使并不会使用到该对象

public interface GrantedAuthority extends Serializable {//获取当前用户所拥有的权限(或角色)信息String getAuthority();
}

UserDetailsService

提供一个接口loadUserByUsername(String username),一般通过扩展该接口显式获取我们的用户信息,用户登陆时传递的用户名和密码也是通过这里查找出来的用户名和密码进行校验,真正的校验由AuthenticationManager和AuthenticationProvider负责的。如果用户不存在时应返回NULL,而是抛出异常UsernameNotFoundException

public interface UserDetailsService {UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}

UserDetails

规范了用户详细信息所拥有的字段,如用户名、密码、账号是否过期、是否锁定等,在SpringSecurity中,获取当前登录的用户的信息,一般情况是需要在该接口上面进行扩展

public interface UserDetails extends Serializable {// 返回权限集合Collection<? extends GrantedAuthority> getAuthorities();// 获取密码String getPassword();// 获取用户名String getUsername();// 判断用户是否未过期boolean isAccountNonExpired();// 判断账户是否未锁定boolean isAccountNonLocked();// 判断用户凭证是否没过期,即密码是否未过期boolean isCredentialsNonExpired();// 判断用户是否可用boolean isEnabled();
}

安全身份认证流程

过滤器链

认证流程

在这里插入图片描述

在线绘图工具,ER模型设计-Spring-Security分析,流程图制作工具,设计流程图,visio流程图,在线流程图制作,如何制作流程图 ...

  1. Spring Security定义了一个过滤器链,当认证请求到达这个链时,该请求将会穿过这个链条用于认证和授权,这个链上可以定义1~N个过滤器,过滤器的用途是获取请求中的认证信息,根据认证方法进行路由,把认证信息传递给对应的认证处理程序进行处理,不同的过滤器处理不同的认证信息
  • HTTP Basic认证通过过滤器链,到达BasicAuthenticationFilter
  • HTTP Digest认证被DigestAuthenticationFilter识别,拦截并处理
  • 表单登录认证被UsernamePasswordAuthenticationFilter识别,拦截并处理
  1. 基于用户凭证创建AuthenticationToken

如:用户在登录表单中输入用户名和密码,并点击确定,浏览器提交POST请求到服务器,穿过过滤器链,被UsernamePasswordAuthenticationFilter识别,UsernamePasswordAuthenticationFilter提取请求中的用户名和密码来创建UsernamePasswordAuthenticationToken对象

  1. 把组装好的AuthenticationToken传递给AuthenticationManager

如:组装好的UsernamePasswordAuthenticationToken对象被传递给AuthenticationManager的authenticate方法进行认证决策,AuthenticationManager只是一个接口,实际的实现是ProviderManager

  1. ProviderManager委托给AuthenticationProvider进行认证处理

AuthenticationProvider提供了不同的实现类,ProviderManager会把收到的UsernamePasswordAuthenticationToken对象传递给列表中的每一个AuthenticationProvider进行认证,那UsernamePasswordAuthenticationToken会被哪一个接收和处理呢?是由supports方法来决定的

  1. UserDetailsService获取用户信息

例如:DaoAuthenticationProvider通过UserDetailsService查找对应的用户信息

  1. 认证结果处理

例如:如果认证成功(用户名和密码完全正确),AuthenticationProvider将会返回一个完全有效的Authentication对象(UsernamePasswordAuthenticationToken),否则抛出AuthenticationException异常

认证完成后,AuthenticationManager将会返回该认证对象(UsernamePasswordAuthenticationToken)返回给过滤器

  1. 存储认证对象。相关的过滤器获得一个认证对象后,把他存储在安全上下文中(SecurityContext)用于后续的授权判断

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

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

相关文章

微信轰炸-python实现方法

新手&#xff0c;一般都需要执行以下命令&#xff0c;用来导入对应模块 pip install -i Simple Index pynput 键盘winr进入输入cmd 执行该命令即可&#xff1a;pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pynput 打开pycharm,输入代码如下 from pynput.keybo…

AI视频智能识别技术在智慧农业大棚升级改造管理场景中的应用方案

一、需求分析 随着科技的进步和农业现代化的推进&#xff0c;智能化技术逐渐成为现代农业发展的重要支撑。农业大棚作为现代农业的重要组成部分&#xff0c;其智能化改造对于提高农业生产效率、降低成本、增加收益具有重要意义。利用先进的信息化手段来对农业大棚进行管理&…

NOC总线(2)

1. NoC的路由 在NoC交换信息时&#xff0c;需要确定从源节点到目标节点所经过的路径&#xff0c;这时就需要路由算法来确定该路径。路由算法分为静态路由算法和动态路由算法两种。 静态路由算法对于两节点之间的路径是固定的&#xff0c;结构简单&#xff0c;便于硬件实…

【算法分析与设计】二叉树的层序遍历

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;算法分析与设计 ⛺️稳中求进&#xff0c;晒太阳 题目 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xf…

idea插件开发

1&#xff0c; file-new project 如图&#xff0c;选择了安装路径&#xff0c;报错【select home directory for intellij platform plugin sdk】。&#xff08;注意是安装路径最外层的文件夹&#xff0c;不是里面的lib&#xff0c;jbr这一层级&#xff09; 2&#xff0c;点击了…

HTML前端CSS实现只显示1行或者2行、3行剩余显示省略号

想要做的效果: 文本只一行显示 /**实现思路&#xff1a;1.设置inline-block属相2.强制不换行3.固定高度4.隐藏超出部分5.显示“……”*/ {display: inline-block;white-space: nowrap; width: 100%; overflow: hidden;text-overflow:ellipsis; }文本只多行显示 /** 实现思路&…

【Java发送邮箱】spring boot 发送邮箱

导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId> </dependency> 2.在properties配置邮箱 # 发件人QQ号 spring.mail.username2508575653qq.com # QQ邮箱授权码 sp…

xshell配置隧道转移规则

钢铁知识库&#xff0c;一个学习python爬虫、数据分析的知识库。人生苦短&#xff0c;快用python。 xshell是什么 通俗点说就是一款强大ssh远程软件&#xff0c;可以方便运维人员对服务器进行管理操作&#xff0c;功能很多朋友们自行探索&#xff0c;今天只聊其中一个功能点那…

HNU-数据挖掘-实验2-数据降维与可视化

数据挖掘课程实验实验2 数据降维与可视化 计科210X 甘晴void 202108010XXX 文章目录 数据挖掘课程实验<br>实验2 数据降维与可视化实验背景实验目标实验数据集说明实验参考步骤实验过程1.对数据进行初步降维2.使用无监督数据降维方法&#xff0c;比如PCA&#xff0c;I…

既是API调试平台也是自动化测试工具?Apipost

Apipost提供可视化的API自动化测试功能&#xff0c;使用Apipost研发人员可以设计、调试接口&#xff0c;测试人员可以基于同一数据源进行测试&#xff0c;Apipost 接口自动化功能在上次更新中进行了逻辑调整&#xff0c;带来更好的交互操作、更多的控制器选择&#xff0c;同时新…

SpringMvc中拦截器的配置及应用

拦截器原理 在 Spring MVC 中&#xff0c;拦截器&#xff08;Interceptor&#xff09;是一种机制&#xff0c;用于拦截请求并在处理程序&#xff08;Controller&#xff09;执行之前或之后执行一些操作。拦截器允许您在请求的不同阶段&#xff08;如处理程序执行前、处理程序执…

AI大模型中的Bert

1.全方位上下文理解&#xff1a;与以前的模型&#xff08;例如GPT&#xff09;相比&#xff0c;BERT能够双向理解上下文&#xff0c;即同时考虑一个词 的左边和右边的上下文。这种全方位的上下文理解使得BERT能够更好地理解语言&#xff0c;特别是在理解词义、 消歧等复杂任务上…

智慧安防GB28181视频监控EasyCVR v3.5系统增加录像保存地址的配置

智慧安防监控EasyCVR视频管理平台能在复杂的网络环境中&#xff0c;将前端设备统一集中接入。在网络传输上&#xff0c;平台支持设备通过4G、5G、WIFI、有线等方式进行视频流的快捷传输&#xff0c;视频流经平台处理后可对外进行多格式的分发&#xff0c;实现多展示终端观看&am…

消息中间件之Kafka(二)

1.Kafka线上常见问题 1.1 为什么要对topic下数据进行分区存储? 1.commit log文件会受到所在机器的文件系统大小的限制&#xff0c;分区之后可以将不同的分区放在不同的机器上&#xff0c; 相当于对数据做了分布式存储&#xff0c;理论上一个topic可以处理任意数量的数据2.提…

TCP高并发服务器简介(select、poll、epoll实现与区别)

select、poll、epoll三者的实现&#xff1a; select实现TCP高并发服务器的流程&#xff1a; 一、创建套接字&#xff08;socket函数&#xff09;&#xff1a;二、填充服务器的网络信息结构体&#xff1a;三、套接字和服务器的网络信息结构体进行绑定&#xff08;bind函数&…

大模型笔记【3】 gem5 运行模型框架LLama

一 LLama.cpp LLama.cpp 支持x86&#xff0c;arm&#xff0c;gpu的编译。 1. github 下载llama.cpp https://github.com/ggerganov/llama.cpp.git 2. gem5支持arm架构比较好&#xff0c;所以我们使用编译LLama.cpp。 以下是我对Makefile的修改 开始编译&#xff1a; make UNAME…

Kotlin协程的JVM实现源码分析(下)

协程 根据 是否保存切换 调用栈 &#xff0c;分为&#xff1a; 有栈协程&#xff08;stackful coroutine&#xff09;无栈协程&#xff08;stackless coroutine&#xff09; 在代码上的区别是&#xff1a;是否可在普通函数里调用&#xff0c;并暂停其执行。 Kotlin协程&…

【git分支管理策略】

文章目录 前言一、分支管理策略简介二、git基本操作三、git分支远程分支本地分支 四、gitflow分支管理策略分支定义gitflow分支管理策略评价 五、GITHUB FLOW分支管理策略分支使用流程创建分支&#xff08;Create a branch&#xff09;新增提交(add and commit)提出 Pull 请求&…

C++泛型编程-类模板的项目实战实现基础的Vector的编写

请设计一个数组模板类&#xff08; Vector &#xff09;&#xff0c;完成对 int 、 char 、 float 、 double 以 及任意的自定义类等类型元素进行管理。 需求 a. 实现构造函数 b. 实现拷贝构造函数 c. 实现 cout << 操作 d. 实现下标访问符 [] 的重载操作 …

CTF-PWN-堆-【chunk extend/overlapping-1】

文章目录 chunk extend/overlappingfastbin与topchunk相邻free时候不会合并unsortedbinchunk中与topchunk相邻的被free时会合并extend向后overlapping先修改header&#xff0c;再free&#xff0c;再malloc先free&#xff0c;再修改header&#xff0c;再malloc extend向前overla…