四、Spring Boot集成Spring Security之认证流程
二、概要说明
- 本文主要介绍登录登出业务流程,所以使用基于内存的用户名密码,暂不介绍授权相关内容,后续会详细介绍基于数据库的认证及授权
- 如何查看基于内存的默认用户名密码
- 如何配置基于内存的自定义用户名密码
- 本文与上文有强关联性,如果对过滤器链中登录相关的过滤器不熟悉的同学,请先查看三、Spring Boot集成Spring Security之securityFilterChain过滤器链详解
三、基于内存的用户名密码
1、默认用户名密码
- 一、Spring Boot集成Spring Security之自动装配中第六节已介绍当用户未自定义认证接口时,生成默认认证接口inMemoryUserDetailsManager,其中用户名为user,密码为随机生成的uuid,项目启动时会打印在控制台中

- 用户名密码源码

2、自定义用户名密码
- 上一小节【用户名密码源码】中配置绑定可以配置自定义用户名、密码
- 通过配置文件配置用户名密码

3、为方便测试添加测试接口TestController
package com.yu.demo.web;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("/hello")
public String hello() {
return "success";
}
}

四、登录登出重要概念介绍
- 安全上下文仓库(SecurityContextRepository):用于存储安全上下文,默认基于session实现(HttpSessionSecurityContextRepository)
- 安全上下文持有者(SecurityContextHolder):用于存储本次请求的安全上下文,默认基于ThreadLocal实现
- 安全上下文(SecurityContext):用于存储认证信息
- 认证信息(Authentication):用于存储用户及认证结果信息,主要实现类有
- 用户名密码认证Token:UsernamePasswordAuthenticationToken
- 匿名认证Token:AnonymousAuthenticationToken
- 登录页面请求:跳转到登录页面的请求
- 登录请求:在登录页面输入用户名密码后提交的请求
- 登出页面请求:跳转到登出页面的请求
- 登出请求:在登出页面确认登出提交的请求
五、登录业务逻辑
1、登录业务相关过滤器
- SecurityContextPersistenceFilter
- UsernamePasswordAuthenticationFilter
- DefaultLoginPageGeneratingFilter
- AnonymousAuthenticationFilter
- ExceptionTranslationFilter
- FilterSecurityInterceptor
2、访问业务请求处理流程
1)、访问业务请求地址被拦截,重定向到登录页面请求
浏览器访问业务请求地址:http://localhost:8080/test/hello
SecurityContextPersistenceFilter处理请求:
- 从安全上下文仓库中获取安全上下文为空,创建没有认证信息的安全上下文(SecurityContextImpl)
- 将第1步中获取的安全上下文设置到安全上下文持有者中
- 执行后续过滤器链
- 源码

AnonymousAuthenticationFilter处理请求:
- 获取安全上下文持有者中的安全上下文中的认证信息为空
- 创建匿名认证信息
- 创建新的没有认证信息的安全上下文
- 将第2步中的匿名认证信息设置到第3步中的安全上下文中
- 将第3步中的安全上下文中设置到安全上下文持有者中
- 执行后续过滤器链
- 源码

FilterSecurityInterceptor处理请求:
- 验证安全上下文持有者中的安全上下文中的匿名认证信息通过
- 验证授权信息失败(业务请求地址未设置可以匿名访问时),抛出AccessDeniedException异常
- 源码

ExceptionTranslationFilter处理请求:
- 捕获FilterSecurityInterceptor抛出的AccessDeniedException异常
- 判断是因为匿名访问导致的授权异常
- 创建新的没有认证信息的安全上下文
- 将第3步中的安全上下文中设置到安全上下文持有者中
- 重定向到登录页面:http://localhost:8080/login
- 源码

SecurityContextPersistenceFilter处理请求:
- 执行chain.doFilter之后的代码
- 获取安全上下文持有者中的安全上下文
- 删除安全上下文持有者中的安全上下文
- 将第2步中获取的安全上下文保存到安全上下文仓库中
- 源码

重定向登录页面请求:http://localhost:8080/login(GET)
2)、重定向定页面请求,返回登录页面
SecurityContextPersistenceFilter处理请求:
- 从安全上下文仓库中获取安全上下文为空,创建没有认证信息的安全上下文(SecurityContextImpl)
- 将第1步中获取的安全上下文设置到安全上下文持有者中
- 执行后续过滤器链
- 源码(同上)
DefaultLoginPageGeneratingFilter处理请求:
- 判断是跳转到登录页面的请求
- 生成默认登录页面
- 返回并渲染生成的默认登录页面
- 源码

SecurityContextPersistenceFilter处理请求:
- 执行chain.doFilter之后的代码
- 获取安全上下文持有者中的安全上下文
- 删除安全上下文持有者中的安全上下文
- 将第2步中获取的安全上下文保存到安全上下文仓库中
- 源码(同上)
3)、输入正确用户名密码,重定向到业务请求
SecurityContextPersistenceFilter处理请求:
- 从安全上下文仓库中获取安全上下文为空,创建没有认证信息的安全上下文(SecurityContextImpl)
- 将第1步中获取的安全上下文设置到安全上下文持有者中
- 执行后续过滤器链
- 源码(同上)
UsernamePasswordAuthenticationFilter处理请求:
- 判断需要认证(AbstractAuthenticationProcessingFilter.doFilter方法)
- 认证用户名密码成功,生成已认证的认证信息UsernamePasswordAuthenticationToken
- 创建新的没有认证信息的安全上下文
- 将第2步中的认证信息设置到第3步中的安全上下文中
- 将第3步中的安全上下文设置到安全上下文持有者中
- 将第3步中的安全上下文保存到局部变量安全上下文仓库中(空实现)
- 重定向到业务请求地址:http://localhost:8080/test/hello
- 源码

SecurityContextPersistenceFilter处理请求:
- 执行chain.doFilter之后的代码
- 获取安全上下文持有者中的安全上下文
- 删除安全上下文持有者中的安全上下文
- 将第2步中获取的安全上下文保存到安全上下文仓库中
- 源码(同上)
4)、重定向到业务请求
SecurityContextPersistenceFilter处理请求:
- 从安全上下文仓库中获取已认证的安全上下文
- 将第1步中获取的安全上下文设置到安全上下文持有者中
- 执行后续过滤器链
- 源码(同上)
FilterSecurityInterceptor处理请求:
- 验证安全上下文持有者中的安全上下文中的认证信息通过
- 验证授权成功
- 调用接口返回数据
- 源码

SecurityContextPersistenceFilter处理请求:
- 执行chain.doFilter之后的代码
- 获取安全上下文持有者中的安全上下文
- 删除安全上下文持有者中的安全上下文
- 将第2步中获取的安全上下文保存到安全上下文仓库中
- 源码(同上)
六、登出业务实现逻辑
1、登出业务相关过滤器
- SecurityContextPersistenceFilter
- LogoutFilter
- DefaultLogoutPageGeneratingFilter
2、访问登出页面请求处理流程
浏览器访问登出请求地址:http://localhost:8080/logout
SecurityContextPersistenceFilter处理请求:
- 从安全上下文仓库中获取已认证的安全上下文
- 将第1步中获取的安全上下文设置到安全上下文持有者中
- 执行后续过滤器链
- 源码(同上)
DefaultLogoutPageGeneratingFilter处理请求:
- 判断是跳转到登出页面的请求
- 生成默认登出页面
- 返回并渲染生成的默认登出页面
- 源码

SecurityContextPersistenceFilter处理请求:
- 执行chain.doFilter之后的代码
- 获取安全上下文持有者中的安全上下文
- 删除安全上下文持有者中的安全上下文
- 将第2步中获取的安全上下文保存到安全上下文仓库中
- 源码(同上)
3、登出页面确认登出请求处理流程
1)、确认登出,重定向到登录页面请求
SecurityContextPersistenceFilter处理请求:
- 从安全上下文仓库中获取已认证的安全上下文
- 将第1步中获取的安全上下文设置到安全上下文持有者中
- 执行后续过滤器链
- 源码(同上)
LogoutFilter处理请求:
- 判断是登出请求
- 获取安全上下文持有者中的安全上下文
- 登出处理器处理登出业务
- 删除安全上下文持有者中的安全上下文
- 创建没有认证信息的安全上下文
- 将第2步中的安全上下文保存到安全上下文仓库中
- 重定向到登录页面
- 源码

SecurityContextPersistenceFilter处理请求:
- 执行chain.doFilter之后的代码
- 获取安全上下文持有者中的安全上下文
- 删除安全上下文持有者中的安全上下文
- 将第2步中获取的安全上下文保存到安全上下文仓库中
- 源码(同上)
2)、登录页面请求
第五节登录业务逻辑已介绍,不再赘述。
七、说明
- Spring Boot集成Spring Security默认是非前后分离架构
- 本文介绍的流程是非前后分离版本的处理流程
- 前后分离处理流程较为简单
- 未认证时访问业务接口,返回未认证错误信息
- 调用登录接口成功后返回Token,此后请求头中携带此Token
- 调用登出接口成功后返回成功,后端将该Token失效
- 携带Token访问业务接口,后端验证Token成功后,调用业务接口并返回数据
四、Spring Boot集成Spring Security之认证流程的更多相关文章
- Spring Boot集成Spring Data Reids和Spring Session实现Session共享
首先,需要先集成Redis的支持,参考:http://www.cnblogs.com/EasonJim/p/7805665.html Spring Boot集成Spring Data Redis+Sp ...
- SpringBoot系列:Spring Boot集成Spring Cache,使用EhCache
前面的章节,讲解了Spring Boot集成Spring Cache,Spring Cache已经完成了多种Cache的实现,包括EhCache.RedisCache.ConcurrentMapCac ...
- SpringBoot系列:Spring Boot集成Spring Cache,使用RedisCache
前面的章节,讲解了Spring Boot集成Spring Cache,Spring Cache已经完成了多种Cache的实现,包括EhCache.RedisCache.ConcurrentMapCac ...
- Spring Boot 集成 Spring Security 实现权限认证模块
作者:王帅@CodeSheep 写在前面 关于 Spring Security Web系统的认证和权限模块也算是一个系统的基础设施了,几乎任何的互联网服务都会涉及到这方面的要求.在Java EE领 ...
- Spring boot 集成Spring Security
依赖jar <dependency> <groupId>org.springframework.cloud</groupId> <artifactId> ...
- Spring Boot 集成spring security4
项目GitHub地址 : https://github.com/FrameReserve/TrainingBoot Spring Boot (三)集成spring security,标记地址: htt ...
- Spring boot集成spring session实现session共享
最近使用spring boot开发一个系统,nginx做负载均衡分发请求到多个tomcat,此时访问页面会把请求分发到不同的服务器,session是存在服务器端,如果首次访问被分发到A服务器,那么se ...
- Spring Boot 集成 Spring Security
1.添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...
- Spring Boot 集成 Spring Security 入门案例教程
前言 本文作为入门级的DEMO,完全按照官网实例演示: 项目目录结构 Maven 依赖 <parent> <groupId>org.springframework.boot&l ...
- Spring Boot 集成 Spring Security 使用自定义的安全数据源
编写一个类自定义实现 UserDetailsService 接口 @Service("customUserDetailService") public class CustomUs ...
随机推荐
- pve 安装配置问题集锦
官网:https://www.proxmox.com/en/ 下载:https://www.proxmox.com/en/downloads 安装:https://pve.proxmox.com/wi ...
- 【转载】 Integrating New Games into Retro Gym
https://medium.com/aureliantactics/integrating-new-games-into-retro-gym-12b237d3ed75 OpenAI's retro ...
- git No url found for submodule path 'xxxxx' in .gitmodules
删除之前的子模块记录 rm -rf git rm --cached 然后加进去 git submodule add
- 多线程之park()与interrupt()的理解
1.背景 其他不多说,很多时候面试会问 2.代码 package com.ldp.demo01; import com.common.MyThreadUtil; import lombok.exter ...
- ubuntu 安装osx 主题 转自linux公社
繁體 你好,游客 登录 注册 搜索 首页Linux新闻Linux教程数据库技术Linux编程服务器应用Linux安全Linux下载Linux认证Linux主题Linux壁纸Linux软件数码手机电脑 ...
- [NOI2007] 项链工厂 题解
前言 题目链接:洛谷:Hydro & bzoj. 题意简述 yzh 喜欢写 DS 题!你要维护一个环: 顺时针移动 \(k\) 位: 翻转 \(2 \sim n\): 交换 \(i\) 与 \ ...
- 我们与高效工作流的距离:使用AI阅读工具ChatDOC+笔记软件Obsidian Slide,直接从 PDF 文献直接输出 PPT 报告
我们与高效工作流的距离 在当今信息化的时代,为了实现高效工作和学习,如何实现快速地输入和输出成为每个人的必修课题. 然而,对于输入而言,每一天大量的信息,往往会使我们陷入信息过载和知识爆炸的困境,难以 ...
- 使用 onBeforeRouteLeave 组合式函数提升应用的用户体验
title: 使用 onBeforeRouteLeave 组合式函数提升应用的用户体验 date: 2024/8/14 updated: 2024/8/14 author: cmdragon exce ...
- 2023 ICPC网络赛第一场(A,D,J,L)
2023 ICPC网络赛第一场(A,D,J,L) A Qualifiers Ranking Rules 先把两场比赛的学校排名处理出来,然后两场比赛的同位次进行合并即可 #include <bi ...
- 我的微服务项目之IdentityServer4
2021,祝大家新年快乐!!! 2021年了,新的一年应该有新的计划,我的计划是准备去学习微服务,所以我将我自己的博客项目拆分成了一个微服务项目,用来给自己学习,项目地址:http://www.tt ...