SpringSecurity源码分析3--UserDetail部分

news2025/3/16 23:03:48

UserDetailsService.class
在这里插入图片描述
DaoAuthenticationProvider.class

在这里插入图片描述

AbstractUserDetailsAuthenticationProvider.class

一个允许子类重写和处理UserDetails对象的基AuthenticationProvider。该类旨在响应UsernamePasswordAuthenticationToken身份验证请求。
在这里插入图片描述

AuthenticationProvider.class

在这里插入图片描述

@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,
				() -> this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.onlySupports",
						"Only UsernamePasswordAuthenticationToken is supported"));
		String username = determineUsername(authentication);
		boolean cacheWasUsed = true;
		UserDetails user = this.userCache.getUserFromCache(username);
		if (user == null) {
			cacheWasUsed = false;
			try {
				user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);
			}
			catch (UsernameNotFoundException ex) {
				this.logger.debug("Failed to find user '" + username + "'");
				// 抛出一个含糊的异常,提供安全保护机制
				if (!this.hideUserNotFoundExceptions) {
					throw ex;
				}
				throw new BadCredentialsException(this.messages
						.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
			}
			Assert.notNull(user, "retrieveUser returned null - a violation of the interface contract");
		}
		try {
			this.preAuthenticationChecks.check(user);
			additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);
		}
		catch (AuthenticationException ex) {
			if (!cacheWasUsed) {
				throw ex;
			}
			// 可能存在用户数据变更的问题,需要再次尝试获取
			// There was a problem, so try again after checking
			// we're using latest data (i.e. not from the cache)
			cacheWasUsed = false;
			user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);
			this.preAuthenticationChecks.check(user);
			additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);
		}
		this.postAuthenticationChecks.check(user);
		if (!cacheWasUsed) {
			this.userCache.putUserInCache(user);
		}
		Object principalToReturn = user;
		if (this.forcePrincipalAsString) {
			principalToReturn = user.getUsername();
		}
		return createSuccessAuthentication(principalToReturn, authentication, user);
	}

获取用户名
在这里插入图片描述

从缓存中获取UserDetail对象

在这里插入图片描述

private UserCache userCache = new NullUserCache();

在这里插入图片描述
默认都是null,可以通过setUserCache设置Cache

this.preAuthenticationChecks.check(user);
在这里插入图片描述

additionalAuthenticationChecks
在这里插入图片描述

密码校验
在这里插入图片描述

public interface PasswordEncoder {
    String encode(CharSequence rawPassword);

    boolean matches(CharSequence rawPassword, String encodedPassword);

    default boolean upgradeEncoding(String encodedPassword) {
        return false;
    }
}

this.postAuthenticationChecks.check(user);
在这里插入图片描述
createSuccessAuthentication
在这里插入图片描述
权限管理

	private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();

在这里插入图片描述retrieveUser

  1. 建议直接抛出UsernameNotFoundException
  2. 时间攻击防护

在这里插入图片描述
通过预先编码这个密码,可以确保在后续的时间攻击防护方法中,不会因为实时编码操作而导致时间差异,这些时间差异可能会被攻击者用来推断密码或其他敏感信息。
在这里插入图片描述
在这里插入图片描述
加密方法升级后,重新更新密码
在这里插入图片描述
在这里插入图片描述

UsernamePasswordAuthenticationFilter.class

在这里插入图片描述
在这里插入图片描述

AbstractAuthenticationProcessingFilter.class
在这里插入图片描述

private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		if (!requiresAuthentication(request, response)) {
			chain.doFilter(request, response);
			return;
		}
		try {
			Authentication authenticationResult = attemptAuthentication(request, response);
			if (authenticationResult == null) {
				// return immediately as subclass has indicated that it hasn't completed
				return;
			}
			// 给session策略提供钩子
			this.sessionStrategy.onAuthentication(authenticationResult, request, response);
			// Authentication success
			if (this.continueChainBeforeSuccessfulAuthentication) {
				chain.doFilter(request, response);
			}
			successfulAuthentication(request, response, chain, authenticationResult);
		}
		catch (InternalAuthenticationServiceException failed) {
			this.logger.error("An internal error occurred while trying to authenticate the user.", failed);
			unsuccessfulAuthentication(request, response, failed);
		}
		catch (AuthenticationException ex) {
			// Authentication failed
			unsuccessfulAuthentication(request, response, ex);
		}
	}

在这里插入图片描述
在这里插入图片描述

FormLoginConfigurer.class
在这里插入图片描述
在这里插入图片描述
默认页面,生产不会使用
在这里插入图片描述
默认密码来源
在这里插入图片描述
默认加载的类
在这里插入图片描述

SecurityConfigurerAdapter.class

链式调用
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

AbstractAuthenticationFilterConfigurer.class在这里插入图片描述

@Override
	public void configure(B http) throws Exception {
		PortMapper portMapper = http.getSharedObject(PortMapper.class);
		if (portMapper != null) {
			this.authenticationEntryPoint.setPortMapper(portMapper);
		}
		// 设置请求缓存器
		RequestCache requestCache = http.getSharedObject(RequestCache.class);
		if (requestCache != null) {
			this.defaultSuccessHandler.setRequestCache(requestCache);
		}
		// 设置处理器
		this.authFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
		this.authFilter.setAuthenticationSuccessHandler(this.successHandler);
		this.authFilter.setAuthenticationFailureHandler(this.failureHandler);
		if (this.authenticationDetailsSource != null) {
			this.authFilter.setAuthenticationDetailsSource(this.authenticationDetailsSource);
		}
		// 设置Session策略
		SessionAuthenticationStrategy sessionAuthenticationStrategy = http
				.getSharedObject(SessionAuthenticationStrategy.class);
		if (sessionAuthenticationStrategy != null) {
			this.authFilter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy);
		}
		// 记住我
		RememberMeServices rememberMeServices = http.getSharedObject(RememberMeServices.class);
		if (rememberMeServices != null) {
			this.authFilter.setRememberMeServices(rememberMeServices);
		}
		// 安全上下文
		SecurityContextConfigurer securityContextConfigurer = http.getConfigurer(SecurityContextConfigurer.class);
		if (securityContextConfigurer != null && securityContextConfigurer.isRequireExplicitSave()) {
			// 安全上下文仓库
			SecurityContextRepository securityContextRepository = securityContextConfigurer
					.getSecurityContextRepository();
			this.authFilter.setSecurityContextRepository(securityContextRepository);
		}
		// 添加过滤器
		F filter = postProcess(this.authFilter);
		http.addFilter(filter);
	}

在这里插入图片描述

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

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

相关文章

Gartner 《2024安全和风险管理技术路线图》:高价值技术 DSP 进入广泛部署阶段

近期,Gartner 发布《2024年技术采用路线图:安全与风险管理》(以下简称:《路线图》),该信息图表识别了全球企业正在采用的 44 种与安全相关的技术,并根据采用阶段、部署风险和企业价值进行了映射…

python中的列表、元组、字典、集合(字典篇)

数据类型定义符号访问元素是否可变是否重复是否有序列表 [ ]索引可变可重复有序元组()索引不可变可重复有序字典{key:value}键可变可重复无序集合{ }可变不可重复无序 字典概念 在python语言中,字典属于内置容器类,其…

什么是云安全

云安全和网络安全有所不同,因为云安全一词 比网络安全更涵盖整个企业基础设施。一般来说,当人们提到云安全时,指的是第三方服务提供商提供的 IaaS 云环境。在这种情况下,云安全不仅包括网络安全工具,还包括服务器、容器…

C#基础|数据类型、变量

哈喽,你好啊,我是雷工! 01 数据类型 数据类型是为了方便存储数据的,为了将数据按照不同的分类存储,所以引入数据类型。这个在PLC中已经很熟悉了。 数据类型的作用:就是为了更好地管理内存,为…

[C++][算法基础]求最小生成树(Prim)

给定一个 n 个点 m 条边的无向图,图中可能存在重边和自环,边权可能为负数。 求最小生成树的树边权重之和,如果最小生成树不存在则输出 impossible。 给定一张边带权的无向图 G(V,E),其中 V 表示图中点的集合,E 表示图…

【深度学习】AI修图——DragGAN原理解析

1、前言 上一篇,我们讲述了StyleGAN2。这一篇,我们就来讲一个把StyleGAN2作为基底架构的DragGAN。DragGAN的作用主要是对图片进行编辑,说厉害点,可能和AI修图差不多。这篇论文比较新,发表自2023年 原论文&#xff1a…

拼多多容器文件修改自动上传

拼多多开放平台php环境是官方的linux容器,不能自己搭建ftp上传文件,每每有文件更新都挺麻烦。 有些功能测试不想每次都打包全部代码上去重新发布一次程序生成新的容器,那样太过麻烦和效率低。 一开始搞了一个php的文件管理工具上去&#xf…

高效解决Visual Studio Code中文乱码问题

文章目录 问题解决步骤 问题 Visual Studio Code新建一个文件编码方式总是默认GBK,如果我不修改成默认UTF-8,那么每次运行,如果有中文需要输出就会乱码! 解决步骤 之后我会持续更新,如果喜欢我的文章,请记…

Apache DolphinScheduler 社区 3 月月报

各位热爱 DolphinScheduler 的小伙伴们,DolphinScheduler 社区月报开始更新啦!这里将记录 DolphinScheduler 社区每月的重要更新。 社区为 DolphinScheduler 3.2.x 版本做了诸多功能改进和 bug 修复 DolphinScheduler 月度 Merge Stars 感谢以下小伙伴 …

腾讯云轻量应用服务器端口怎么打开?

腾讯云轻量应用服务器端口怎么打开?在轻量应用服务器控制台的防火墙中开启端口,本文腾讯云百科txybk.com以80端口为例,来详细说下轻量应用服务器端口打开教程,另外可以在腾讯云百科 txy.wiki 查看当前轻量服务器最新的优惠券和配置…

LSTM 循环神经网络原理深度解读与网络结构精细剖析

长短期记忆网络(Long Short-Term Memory, LSTM)是一种特殊的循环神经网络(Recurrent Neural Network, RNN),设计用于解决长期依赖问题,特别是在处理时间序列数据时。 循环神经网络(RNN&#xf…

jenkins(docker)安装及应用

jenkins Jenkins是一个开源的、提供友好操作界面的持续集成(CI)工具,起源于Hudson(Hudson是商用的),主要用于持续、自动的构建/测试软件项目、监控外部任务的运行(这个比较抽象,暂且写上,不做解…

【InternLM】LMDeploy部署实践

1. LMDeploy基本介绍 LMDeploy提供一站式的大模型压缩、部署和服务,其主要特点包括: 高效的推理速度。通过引入持久批处理(即连续批处理)、阻塞 KV 缓存、动态拆分与融合、张量并行、高性能 CUDA 内核等关键特性,提供了比 vLLM 高1.8倍的请…

从零开始写一个RTSP服务器(三)RTP传输H.264

目录 一、RTP封装1.1 RTP数据结构1.2 源码 二、H.264的RTP打包2.1 H.264格式2.2 H.264的RTP打包方式2.3 H.264 RTP包的时间戳计算2.4 源码 三、H.264 RTP打包的sdp描述四、测试 本篇文章目标,使用vlc打开sdp文件后,可以观看到视频数据 一、RTP封装 1.1 …

实战:完美解决md图床问题-nginx图床-2024.4.16(测试成功)

目录 文章目录 目录1、前言图床简介搭建方式需求背景解决方案 2、配置过程1.部署nginx服务2.配置picgo3.配置rsync服务(可选) 3、测试验证关于我最后最后 1、前言 图床简介 对于写博客的朋友们来讲,图床这个东西一定不会陌生,而且在一定程度上也给大家…

MySQL8.0.20 下载与安装

一、下载 MySQL服务器下载安装: 官网社区版地址: https://downloads.mysql.com/archives/installer/ 二、安装 安装注意事项---成功秘诀 安装密码不要设置复杂了,千万要记住密码,比如root和mysql就很好;不要随意卸…

4.Spring AOP

4.1 Spring AOP的基本概念 4.1.1 AOP的概念 在业务处理代码中,通常都有日志记录、性能统计、安全控制、事务处理、异常处理等操作。尽管使用OOP可以通过封装或继承的方式达到代码的重用,但仍然存在同样的代码分散到各个方法中。因此,采用OO…

文件上传App,H5,小程序多端兼容

插件地址&#xff1a;https://ext.dcloud.net.cn/plugin?id5459 下载lsj-upload插件 代码如下 结构 <lsj-upload :option"option" :size"size" :formats"formats" :debug"debug":instantly"instantly" change"…

网络编程(现在不重要)

目录 网络编程三要素与InetAddress类的使用 软件架构 面临的主要问题 网络编程三要素&#xff08;对应三个问题&#xff09; InetAddress的使用 TCP与UDP协议剖析与TCP编程案例&#xff08;了解&#xff09; TCP协议 UDP协议 例子 UDP、URL网络编程 URL&#xff1a;&…

Android多线程:Handler runOnUiThread 异步消息处理机制

目录 一&#xff0c;Android中的多线程问题 1.模拟耗时工作 2.Android开启子线程 二&#xff0c;在子线程中更新UI 1.异步消息处理机制 Handler 2.使用runOnUiThread更新UI 一&#xff0c;Android中的多线程问题 Android用户界面是与用户交互的接口&#xff0c;对于用户的…