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

news2024/10/2 10:38:55

获取用户信息

// 获取安全上下文对象,就是那个保存在 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 会对新的策略对象执行一次初始化,相应的该值会增1
	private 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_THREADLOCAL
			strategyName = 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 strategy
			try {
				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.coloradmin.cn/o/1402330.html

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

相关文章

免费的WordPress插件大全

在当今数字化的时代&#xff0c;拥有一个强大的在线存在变得至关重要。而对于使用WordPress建站的用户来说&#xff0c;插件是提高网站功能的关键。在这篇文章中&#xff0c;我们将为您推荐三款免费的WordPress插件&#xff0c;它们不仅是147SEO软件中的佼佼者&#xff0c;而且…

makefile的机制,执行命令的流程分析

makefile的机制&#xff0c;流程分析 calc:add.o sub.o multi.ogcc add.o sub.o multi.o calc.cpp -o calcadd.o:add.cppgcc -c add.cpp -o add.osub.o:sub.cppgcc -c sub.cpp -o sub.omulti.o:multi.cppgcc -c multi.cpp -o multi.oclean:rm -rf *.o calc按照这个例子分析&am…

Flash读取数据库中的数据

Flash读取数据库中的数据 要读取数据库的记录&#xff0c;首先需要建立一个数据库&#xff0c;并输入一些数据。数据库建立完毕后&#xff0c;由Flash向ASP提交请求&#xff0c;ASP根据请求对数据库进行操作后将结果返回给Flash&#xff0c;Flash以某种方式把结果显示出来。 …

Spring | Srping AOP (AOP简介、动态代理、基于“代理类”的AOP实现)

目录: 1.Spring AOP简介1.1 AOP简介1.2 AOP术语 2.动态代理2.1 JDK动态代理2.2 CGLIB代理 3.基于“代理类”的AOP实现3.1 Spring的通知类型3.2 ProxyFactoryBean ( 可通知.xml配置文件完成aop功能 ) 1.Spring AOP简介 1.1 AOP简介 Spring的AOP模块&#xff0c;是Spring框架体系…

nginx基于IP的多虚拟主机

结合这篇文章一起&#xff1a;nginx虚拟主机-CSDN博客文章浏览阅读63次。虚拟主机指的就是一个独立的站点配置&#xff0c;是nginx默认支持的一个功能&#xff0c;它能够有自己独立的域名&#xff0c;独立的ip&#xff0c;独立的端口配置&#xff0c;能够配置完整的www服务&…

<信息安全>《2 国内主要企业网络安全公司概览(二)》

4 北京天融信科技有限公司(简称天融信) 信息内容LOGO成立日期创始于1995年总部北京市海淀区上地东路1号院3号楼北侧301室背景民营企业是否上市天融信[002212]A股市值99亿主要产品网络安全大数据云服务员工规模6000多人简介天融信科技集团&#xff08;证券代码&#xff1a;0022…

基于内容的图像web检索系统

题目&#xff1a;基于内容的图像在线检索系统 简介&#xff1a;基于内容的图像在线检索系统&#xff08;Content Based Online Image Retrieval , 以下简称 CBOIR&#xff09;&#xff0c;是计算机视觉领域中关注大规模数字图像内容检索的研究分支。典型的CBOIR系统&#xff…

使用Python对音频进行特征提取

在几年前写的使用Python对音频进行特征提取使用的是人为特征的方法进行特征提取的&#xff0c;近些年随着深度学习的普及&#xff0c;这里尝试使用深度学习方法进行特征提取。 数据集测试 之前的数据集找不到了&#xff0c;这个数据其实是kaggle的一个数据&#xff1a;www.ka…

ElasticSearch集群灾难:别放弃,也许能再抢救一下 | 京东云技术团队

1 前言 Elasticsearch作为一个分布式搜索引擎&#xff0c;自身是高可用的&#xff1b;但也架不住一些特殊情况的发生&#xff0c;如&#xff1a; 集群超过半数的master节点丢失&#xff0c;ES的节点无法形成一个集群&#xff0c;进而导致集群不可用&#xff1b; 索引shard的文…

蔚来卖一辆车亏20万,去年前三季度巨亏153亿

作为曾经的造车新势力“老大哥”蔚来&#xff0c;一边发布全新旗舰车型ET9预售价80万引争议&#xff0c;一边交付量在新势力垫底&#xff1b;更加“雪上加霜”的是&#xff0c;业绩亏损继续扩大。 「不二研究」据蔚来汽车三季报发现&#xff1a;今年三季度&#xff0c;蔚来净亏…

PyTorch深度学习实战(31)——生成对抗网络(Generative Adversarial Network, GAN)

PyTorch深度学习实战&#xff08;31&#xff09;——生成对抗网络 0. 前言1. GAN2. GAN 模型分析3. 利用 GAN 模型生成手写数字小结系列链接 0. 前言 生成对抗网络 (Generative Adversarial Networks, GAN) 是一种由两个相互竞争的神经网络组成的深度学习模型&#xff0c;它由…

基于taro搭建小程序多项目框架,记重点了!!!

前言 为什么需要这样一个框架&#xff0c;以及这个框架带来的好处是什么&#xff1f; 从字面意思上理解&#xff1a;该框架可以用来同时管理多个小程序&#xff0c;并且可以抽离公用组件或业务逻辑供各个小程序使用。当你工作中面临这种同时维护多个小程序的业务场景时&#…

react umi/max 页签(react-activation)

思路&#xff1a;通过react-activation实现页面缓存&#xff0c;通过umi-plugin-keep-alive将react-activation注入umi框架&#xff0c;封装页签组件最后通过路由的wrappers属性引入页面。 浏览本博客之前先看一下我的博客实现的功能是否满足需求&#xff0c;实现功能&#xf…

日常常见应用组件升级记录

一、前言 因近期安全扫描&#xff0c;发现java后端应用涉及多个引用组件版本过低&#xff0c;涉及潜在漏洞利用风险&#xff0c;特记录相关处理升级处理过程&#xff0c;以备后续确认&#xff1b; 二、升级处理过程 2.1、Java类应用内置Spring Boot版本升级 Spring Boot是一…

【数据结构与算法】之字符串系列-20240121

这里写目录标题 一、344. 反转字符串二、125. 验证回文串三、205. 同构字符串四、242. 有效的字母异位词五、290. 单词规律 一、344. 反转字符串 简单 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额…

java SSM政府采购管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM政府采购管理系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代 码和数据库&#xff0c;系统主要采…

【UE5】第一次尝试项目转插件(Plugin)的时候,无法编译

VS显示100条左右的错误&#xff0c;UE热编译也不能通过。原因可能是[名字.Build.cs]文件的错误&#xff0c;缺少一些内容&#xff0c;比如说如果要写UserWidget类&#xff0c;那么就要在 ]名字.Build.cs] 中加入如下内容&#xff1a; public class beibaoxitong : ModuleRules …

UML序列图入门

使用工具&#xff1a;processOn可免费建9个文件 UML&#xff1a;Unified Modeling Language 统一建模语言 ProcessOn - 我的文件 一、介绍 序列图是基于对象而非基于类&#xff1b; 从上到下&#xff1a;展示了处理过程中&#xff0c;每个对象的生命周期&#xff1b; 从左到…

从白子画到东方青苍,你选择谁来守护你的修仙之旅?

从白子画到东方青苍,你选择谁来守护你的修仙之旅? 在繁花似锦的修仙世界中&#xff0c;每一位追梦者都渴望有那么一位守护者&#xff0c;与你共患难&#xff0c;共成长。热血与浪漫交织的《花千骨》与《苍兰诀》&#xff0c;给我们带来了两位风华绝代的守护者&#xff1a;白子…

ST-GCN 人体姿态估计模型 代码实战

构建一个ST-GCN&#xff08;Spatio-Temporal Graph Convolutional Network&#xff09;模型需要结合图卷积网络&#xff08;GCN&#xff09;的思想&#xff0c;以处理时空数据。以下是一个简单的例子&#xff0c;演示如何使用PyTorch构建ST-GCN模型&#xff1a; import torch …