SpringSecurity中用户表单登录验证源码分析

news2025/3/12 23:41:42

SpringSecurity简单介绍

Spring Security所解决的问题就是安全访问控制,安全访问控制功能其实就是对所有进入系统的请求进行拦截,校验每个请求是否能够访问它所期望的资源。通过学习SpringMVC我们得知只有进入Controller的请求才会走拦截器(Interceptor),而过滤器可以过滤所有的请求,因此可以通过Filter来实现,SpringSecurity对Web资源的保护是就是靠一大串Filter实现的。

当初始化Spring Security时,会创建一个名为 SpringSecurityFilterChain 的Servlet过滤器,类型为org.springframework.security.web.FilterChainProxy,其实现了javax.servlet.Filter,外部的请求都会经过此类
在这里插入图片描述
FilterChainProxy 是一个代理,真正起作用的是FilterChainProxy中SecurityFilterChain所包含的各个Filter,同时这些Filter作为Bean被Spring管理,它们是Spring Security核心,各有各的职责,但他们并不直接处理用户的认证,也不直接处理用户的授权,而是把它们交给了身份认证管理器(AuthenticationManager)和访问决策管理器(AccessDecisionManager)进行处理,
通过上面的介绍我们知道AuthenticationManager接口的实现类里面维护了一个List<ManagerProvider>,ManagerProvider提供多种实现类,每个实现类可以有自己的身份认证方式,比如短信验证、邮箱验证、表单验证等,其中DaoAuthenticationProvier就是专门处理表单验证的
在这里插入图片描述

在这里插入图片描述

表单认证分析

在这里插入图片描述

  1. 用户提交用户名、密码被SecurityFilterChain中的 UsernamePasswordAuthenticationFilter 过滤器获取到,封装为请求Authentication,通常情况下是UsernamePasswordAuthenticationToken这个实现类。

    在这里插入图片描述

  2. 然后过滤器将Authentication提交至认证管理器(AuthenticationManager)进行认证
    在这里插入图片描述

  3. 认证成功后, AuthenticationManager 身份管理器返回一个被填充满了信息的(包括上面提到的权限信息,身份信息,细节信息,但密码通常会被移除) Authentication 实例。

  4. SecurityContextHolder 安全上下文容器将第3步填充了信息的 Authentication ,通过SecurityContextHolder.getContext().setAuthentication(…)方法,设置到其中。可以看出AuthenticationManager接口(认证管理器)是认证相关的核心接口,也是发起认证的出发点,它的实现类为ProviderManager。而Spring Security支持多种认证方式,因此ProviderManager维护着一个List 列表,存放多种认证方式,最终实际的认证工作是由AuthenticationProvider完成的。咱们知道web表单的对应的AuthenticationProvider实现类为DaoAuthenticationProvider,它的内部又维护着一个UserDetailsService负责UserDetails的获取。最终AuthenticationProvider将UserDetails填充至Authentication
    在这里插入图片描述

AuthenticationProvider接口:

在这里插入图片描述

AbstractUserDetailsAuthenticationProvider抽象类

在这里插入图片描述


	private String determineUsername(Authentication authentication) {
		return (authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication.getName();
	}

	@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);
			}
			........................
			try {
				this.preAuthenticationChecks.check(user);
				additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);
		}
		...................
	}

在这里插入图片描述

DaoAuthenticationProvider

在这里插入图片描述

protected void additionalAuthenticationChecks(UserDetails userDetails,
			UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
		if (authentication.getCredentials() == null) {
			this.logger.debug("Failed to authenticate since no credentials provided");
			throw new BadCredentialsException(this.messages
					.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
		}
		String presentedPassword = authentication.getCredentials().toString();
		if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
			this.logger.debug("Failed to authenticate since password does not match stored value");
			throw new BadCredentialsException(this.messages
					.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
		}
	}
protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
			throws AuthenticationException {
		prepareTimingAttackProtection();
		try {
			//执行ServiceImpl中重写了UserDetailsService的loadUserByUsername()
			UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username);
			if (loadedUser == null) {
				throw new InternalAuthenticationServiceException(
						"UserDetailsService returned null, which is an interface contract violation");
			}
			return loadedUser;
		}
}
protected UserDetailsService getUserDetailsService() {
		//获取到的实现了UserDetailsService的我们自定义的ServiceImpl对象
		return this.userDetailsService;
	}

自定义的ServiceImpl实现了UserDetailsService接口

@Service
public class UserServiceImpl implements UserService, UserDetailsService {
    @Autowired
    private UserBeanMapper userBeanMapper;


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //根据用户名从数据库获取密码
        UserBean user = userBeanMapper.selectByUserName(username);
        if(null==user){
            throw new UsernameNotFoundException("用户名不存在");
        }
        //根据用户id从数据库获取用户的权限
        List<String> pers = userBeanMapper.selectPermissionCodeByUserId(user.getUserId());
        //将获取到的用户权限一个个放进List<SimpleGrantedAuthority>中
        for(String per : pers){
            user.getPermission().add(new SimpleGrantedAuthority(per));
        }
        return user;
    }

在这里插入图片描述

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

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

相关文章

LOL自动走A和释放技能原理及安全防护

走A和自动释放技能并不什么变态功能&#xff0c;他的一切操作都是符合常理的&#xff0c; 但是在经过合理的逻辑代码编写后&#xff0c; 利用读取内存数据&#xff0c;快速执行和判断&#xff0c; 实现的功能却是超出大部分玩家的。 也就是说用这个功能&#xff0c;可以弥补…

Spring Security实战(二)—— 实现图形验证码

目录 一. 使用过滤器实现图形验证码 1. 自定义过滤器 2. 图形验证码过滤器 &#xff08;1&#xff09;引入kaptcha依赖 &#xff08;2&#xff09;配置一个 kaptcha 实例 &#xff08;3&#xff09;创建一个CaptchaController&#xff0c;用于获取图形验证码 &#xff08…

[论文速览] Sparks of Artificial General Intelligence: Early experiments with GPT-4

Sparks of Artificial General Intelligence: Early experiments with GPT-4 2023.3.22 微软官方发布了目前人类史上最强AI模型 GPT-4 的综合能力评估论文&#xff0c;总所周知&#xff0c;2023年是通用人工智能&#xff08;Artificial General Intelligence&#xff0c;AGI&a…

18从零开始学Java之switch分支语句中该怎么用?

作者&#xff1a;孙玉昌&#xff0c;昵称【一一哥】&#xff0c;另外【壹壹哥】也是我哦 CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者 前言 在上一篇文章中&#xff0c;壹哥给大家介绍了Java里的顺序、分支、循环结构的概念&#xff0c;并且重点给大家讲解了分支结…

WebSocket和Socket编程

面试一般会问 socket原理 socket为啥要有端口&#xff1a;确定一个链路的是一个四元组 Socket编程 socket通信 你做过socket编程吗&#xff0c;socket是怎么实现知道有连接过来的 说说WebSocket与socket的区别 先谈谈Websocket与Socket的区别 首先Socket 不属于协议范畴 &a…

处理用户输入

shell脚本编程系列 传递参数 向shell脚本传递数据的最简单方法是使用命令行参数 比如 ./add 10 30读取参数 bash shell会将所有的命令行参数都指派给位置参数的特殊变量。其中$0对应脚本名、$1是第一个参数、$2是第二个参数&#xff0c;依次类推&#xff0c;直到$9 #!/bin/b…

Unity3D打包WebGL并使用MQTT(二):使用json

Unity3D打包WebGL并使用MQTT(二):使用json 1. 软件环境 Unity: 2021.3stomp.js 2.3.3: 下载地址:https://www.jsdelivr.com/package/npm/stompjs 2. 内容介绍 这篇博客的主要内容是记录将一个Unity项目打包成WebGL项目&#xff0c;并集成MQTT进行json数据传输的过程。 3. …

〖Python网络爬虫实战⑬〗- XPATH实战案例

订阅&#xff1a;新手可以订阅我的其他专栏。免费阶段订阅量1000python项目实战 Python编程基础教程系列&#xff08;零基础小白搬砖逆袭) 说明&#xff1a;本专栏持续更新中&#xff0c;目前专栏免费订阅&#xff0c;在转为付费专栏前订阅本专栏的&#xff0c;可以免费订阅付费…

一篇文章理解堆栈溢出

一篇文章理解堆栈溢出引言栈溢出ret2text答案ret2shellcode答案ret2syscall答案栈迁移答案堆溢出 unlink - UAF堆结构小提示向前合并/向后合并堆溢出题答案引言 让新手快速理解堆栈溢出&#xff0c;尽可能写的简单一些。 栈溢出 代码执行到进入函数之前都会记录返回地址到SP…

wsl区分和切换,安装NVIDIA驱动+cuda+ffmpeg

wsl区分和切换&#xff0c;安装NVIDIA驱动cudaffmpeg 安装Nvidia驱动 打开terminal wsl --update进入wsl nvidia-smi网上找了一些博客&#xff0c;获取信息&#xff1a; window安装好驱动即可wsl有1和2 我的win10已经安装了驱动 wsl1和wsl怎么区分&#xff1f;切换 区分…

实时聊天提示的最佳做法

本文将教您更多关于有效的实时聊天功能对您的品牌的重要性&#xff0c;以及您可以使用的一些最佳实践来确保您的实时聊天功能尽可能好。实时聊天提示是为您的网站访问者显示的自动聊天消息。在SaleSmartly&#xff08;ss客服&#xff09;中&#xff0c;如您将聊天插件安装到您的…

Win10 安装 MongoDB 5.0.16

一、MongoDB 的官方&#xff1a;http://www.mongodb.com/ 下载&#xff1a;​ ​https://www.mongodb.com/download-center/community​ 二、下载msi文件&#xff0c;双击该文件进行安装。 &#xff08;1&#xff09;打开对话框 ,单击“Next” &#xff08;2&#xff09;请勾…

总结815

4月&#xff08;复习完高数18讲内容&#xff0c;背诵21篇短文&#xff0c;熟词僻义300词基础词&#xff09; 4.8 英语&#xff1a;早上继续背昨天没背完的第15篇文章单词&#xff0c;感觉效率极高&#xff0c;可能是昨晚睡眠质量特别好。下午抄写第16篇文章每日一句长难句看《…

Meetup 直播预告|助力企业数字化转型,8 大微服务容器开源实践亮点抢先看

随着数字化、智能化发展趋势不断加快&#xff0c;大中小型企业纷纷将企业“上云”提上日程&#xff0c;推动企业数字化转型。云时代下&#xff0c;企业需要新技术架构&#xff0c;使之更好地利用云计算优势&#xff0c;让业务更敏捷、成本更低、可伸缩性更强&#xff0c;云原生…

进程概念详解

目录 进程是什么&#xff1f; 描述进程&#xff1a;进程控制块-PCB task_struct task_struct 是什么&#xff1f; task_struct内容分类 组织进程 查看进程 fork创建子进程 进程状态 僵尸进程 孤儿进程 进程优先级 其他概念 进程是什么&#xff1f; 一般书上…

【微信小程序】父子组件之间传值

微信小程序父子组件之间传值有两种&#xff1a; 1.父组件向子组件传值 2.子组件向父组件传值 区别&#xff1a; 父向子传值使用的是属性绑定&#xff0c;子组件中的properties对象进行接收父组件传递过来的值。子向父传值使用的是自定义事件&#xff0c;父组件通过自定义事件…

VUE 学习笔记(一)开发环境搭建

1、Visual Studio Code安装及使用 下载地址官网&#xff1a;https://code.visualstudio.com/ 直接点击下载按钮即可&#xff0c;会根据系统自动下载合适的版本&#xff0c;无需自行选择。 2、VSCode 上安装&#xff1a;JavaScript Debugger 目前 Debugger for Chrome 已经处…

基于html+css的盒子内容旋转

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

【目标检测论文阅读笔记】Reducing Label Noise in Anchor-Free Object Detection

&#xff08;Augmentation for small object detection&#xff09; Abstract 当前的 anchor-free无锚目标检测器 将空间上落在真值框预定义中心区域内的所有特征标记为正。这种方法会在训练过程中产生 标签噪声&#xff0c;因为这些 正标记的特征中的一些 可能位于背景或遮挡…

2023最新8个电脑必装软件,新电脑装完好用又高效

新买的笔记本电脑到手了&#xff0c;需要安装什么软件&#xff1f;不会真的有人这样问吧&#xff0c;万一真的有人不知道需要安装什么软件呢&#xff1f;好吧&#xff0c;提醒一下各位&#xff0c;新电脑不要乱安装软件啊&#xff0c;不然电脑很容易中病毒的。根据我多次换电脑…