二、Spring Security默认认证流程及其优缺点

1、Spring Security默认认证流程总结

四、Spring Boot集成Spring Security之认证流程详细介绍了认证流程,其核心流程如下

  1. SecurityContextPersistenceFilter:chain.doFilter()前从安全上下文仓库中获取安全上下文,未登录状态时获取未认证的安全上下文;chain.doFilter()后从安全上下文持有者中获取安全上下文并更新到安全上下文仓库中
  2. LogoutFilter:如果是登出请求,清除安全上下文认证信息并重定向到登录页面,否则不处理
  3. UsernamePasswordAuthenticationFilter:如果是登录请求,校验请求参数中的用户名密码,校验成功后生成新的已认证的安全上下文并保存到安全上下文仓库中后重定向到目标URL,否则不处理
  4. DefaultLoginPageGeneratingFilter:如果是登录页面请求,返回默认登录页面,否则不处理
  5. DefaultLogoutPageGeneratingFilter:如果是登出页面请求,返回默认登出页面,否则不处理

2、优缺点

  1. 提供了完整的安全的认证流程
  2. 默认基于session实现非前后分离项目的认证流程,该流程已经慢慢退出历史舞台
  3. 未提供前后分离认证流程

三、前后分离项目认证思路

1、前后分离项目认证流程(基于默认流程优化)

  1. 前端输入用户名密码提交到后端
  2. 后端获取到用户名密码并校验,校验成功后生成token(类似于sessionId)返回给前端,生成已认证的安全上下文(类似于session)存储到安全上下文仓库中
  3. 前端获取到token,后续每次请求的请求头中都携带该token(类似于cookie)
  4. 后端获取请求头中的token,通过token获取安全上下文,并设置到安全上下文持有者中
  5. 前端提交退出请求时,后端获取请求头中的token,并通过token删除安全上下文仓库中安全上下文

2、前后分离项目认证流程关键组件对应的默认实现

从前后分离项目认证流程可以看出有四个关键组件

  1. 每次请求时通过请求头中token从安全上下文仓库中获取安全上下文的过滤器(默认SecurityContextPersistenceFilter)
  2. 登出时通过请求头中的token从安全上下文仓库中清除安全上下文的过滤器(默认LogoutFilter)
  3. 登录时验证用户名密码并生成token和安全上下文,将安全上下文添加到安全上下文仓库中的过滤器(默认UsernamePasswordAuthenticationFilter)
  4. 安全上下文仓库(默认HttpSessionSecurityContextRepository)

3、默认实现的局限性

  1. UsernamePasswordAuthenticationFilter从form表单中获取请求参数,不符合RESTFUL开发规范
  2. 认证的关键组件AuthenticationManager未注入到Spring容器中,导致自定义认证过滤器无法直接从Spring容器中获取
  3. UsernamePasswordAuthenticationFilter只实现了认证部分,认证成功后生成的安全上下文并添加安全上下文仓库中过程无法控制,只能使用默认的HttpSession或RequestAttributes方式,无法自定义

4、整改思路

  1. 自定义SecurityContextRepositoryImpl实现安全上下文仓库SecurityContextRepository,实现基于分布式缓存的安全上下文仓库
  2. 自定义RestfulUsernamePasswordAuthenticationFilter继承AbstractAuthenticationProcessingFilter,实现符合RESTFUL开发规范的登录方式
  3. 自定义UserDetailsImpl实现UserDetails接口,方便添加自定义属性
  4. 自定义UserDetailsServiceImpl实现UserDetailsService接口,实现基于数据库的认证方式,并生成token设置到UserDetails中

5、整改后的认证流程

  1. 前端输入用户名密码提交到后端
  2. 后端AbstractAuthenticationProcessingFilter调用子类RestfulUsernamePasswordAuthenticationFilter的attemptAuthentication方法获取认证信息
  3. RestfulUsernamePasswordAuthenticationFilter获取请求中的用户名密码,并调用UserDetailsService的loadUserByUsername获取用户信息
  4. UserDetailsServiceImpl通过用户名查询用户,将用户信息设置到创建的UserDetailsImpl对象中,生成token设置到UserDetailsImpl对象中
  5. AbstractAuthenticationProcessingFilter调用SecurityContextRepositoryImpl保存安全上下文
  6. SecurityContextRepositoryImpl获取安全上下文及其认证信息中的token,将token和安全上下文添加到分布式缓存中
  7. 将token返回到前端
  8. 前端获取token,每次请求时都在请求头中携带该token
  9. SecurityContextPersistenceFilter/SecurityContextHolderFilter调用SecurityContextRepositoryImpl的loadContext获取安全上下文
  10. SecurityContextRepositoryImpl获取请求头中token,使用token从分布式缓存中获取安全上下文并返回
  11. 前端提交登出请求
  12. LogoutFilter调用SecurityContextRepositoryImpl的saveContext,其中参数安全上下文为空值安全上下文
  13. SecurityContextRepositoryImpl判断出空值安全上下文,获取请求头中的token,使用token删除分布式缓存中获取安全上下文

四、总结

1、设计前后分离项目认证流程原则

  1. 尽可能贴合原生Spring Security处理流程,尽量使用Spring Security提供的组件
  2. 接口设计符合RESTFUL接口规范
  3. 使用分布式缓存存储登录凭证,更适合分布式项目

2、其他说明

  1. 这里说的前后分离项目认证流程最佳方案,是个人认为的最佳方案,并非行业公认的最佳方案,一千个读者就有一千个哈姆雷特,欢迎在评论区或者私信讨论你心中的最佳方案
  2. 下文代码实现该方案,敬请期待

六、Spring Boot集成Spring Security之前后分离认证流程最佳方案的更多相关文章

  1. Spring Boot集成Spring Data Reids和Spring Session实现Session共享

    首先,需要先集成Redis的支持,参考:http://www.cnblogs.com/EasonJim/p/7805665.html Spring Boot集成Spring Data Redis+Sp ...

  2. SpringBoot系列:Spring Boot集成Spring Cache,使用EhCache

    前面的章节,讲解了Spring Boot集成Spring Cache,Spring Cache已经完成了多种Cache的实现,包括EhCache.RedisCache.ConcurrentMapCac ...

  3. SpringBoot系列:Spring Boot集成Spring Cache,使用RedisCache

    前面的章节,讲解了Spring Boot集成Spring Cache,Spring Cache已经完成了多种Cache的实现,包括EhCache.RedisCache.ConcurrentMapCac ...

  4. Spring Boot 集成 Spring Security 实现权限认证模块

    作者:王帅@CodeSheep   写在前面 关于 Spring Security Web系统的认证和权限模块也算是一个系统的基础设施了,几乎任何的互联网服务都会涉及到这方面的要求.在Java EE领 ...

  5. Spring boot 集成Spring Security

    依赖jar <dependency> <groupId>org.springframework.cloud</groupId> <artifactId> ...

  6. Spring Boot 集成spring security4

    项目GitHub地址 : https://github.com/FrameReserve/TrainingBoot Spring Boot (三)集成spring security,标记地址: htt ...

  7. Spring boot集成spring session实现session共享

    最近使用spring boot开发一个系统,nginx做负载均衡分发请求到多个tomcat,此时访问页面会把请求分发到不同的服务器,session是存在服务器端,如果首次访问被分发到A服务器,那么se ...

  8. Spring Boot 集成 Spring Security

    1.添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  9. Spring Boot 集成 Spring Security 入门案例教程

    前言 本文作为入门级的DEMO,完全按照官网实例演示: 项目目录结构 Maven 依赖 <parent> <groupId>org.springframework.boot&l ...

  10. Spring Boot 集成 Spring Security 使用自定义的安全数据源

    编写一个类自定义实现 UserDetailsService 接口 @Service("customUserDetailService") public class CustomUs ...

随机推荐

  1. 如何让您的 .NET应用程序更智能-- 请参加 8.20 的 .NET Conf -- Focus on AI

    Microsoft 将于 2024 年 8 月 20 日举办免费的 .NET Conf: Focus on AI.该虚拟活动为开发人员提供了如何集成 .NET 和 AI 以增强应用程序开发和用户体验的 ...

  2. 安卓如何设置开机启动某个程序?init.rc给你搞定

    一.如何设置开机启动某个程序? 1.需求描述 最近有个项目需要在Android开机启动之后,自动执行一个C语言编写的程序:pengd 该程序运行时需要修改网络ip地址及其他网络操作,所以需要root权 ...

  3. .NETCore 服务的三种生命周期

    一.接口定义 public interface ITestSerivceSingleton { public string GetServiceNameBase() { return "IT ...

  4. DDD是软件工程的第一性原理?

    本文书接上回<DDD建模后写代码的正确姿势>,关注公众号(老肖想当外语大佬)获取信息: 最新文章更新: DDD框架源码(.NET.Java双平台): 加群畅聊,建模分析.技术实现交流: 视 ...

  5. freertos总结

    freertos学习总结:(别人的)https://blog.csdn.net/qq_39397153/article/details/123997346 freertos学习笔记:(别人的)http ...

  6. Kali初次使用,如何获得root权限?【转】

    最新的kali 系统,安装的时候会创建一个新用户,不是root的,然后安装软件的时候会要求root权限,要启用root账号可以按下面这个写的 方法1已经确认可以.方法2没尝试,自己试试吧. 1.确定用 ...

  7. 【YashanDB知识库】离线升级一章22.2不支持直接升级到23.1

    [标题]离线升级一章22.2不支持直接升级到23.1 [问题分类]文档问题 [关键词]YashanDB, 离线升级, 版本兼容 [问题描述]文档中提到22.2版本不支持直接升级到23.1. [问题原因 ...

  8. Kubelet证书自动续签(为 kubelet 配置证书轮换)

    1.概述 Kubelet 使用证书进行 Kubernetes API 的认证. 默认情况下,这些证书的签发期限为一年,所以不需要太频繁地进行更新. Kubernetes 包含特性 Kubelet 证书 ...

  9. 为什么Java已经不推荐使用Stack了?

    为什么不推荐使用Stack Java已不推荐使用Stack,而是推荐使用更高效的ArrayDeque 为什么不推荐使用 性能低:是因为 Stack 继承自 Vector, 而 Vector 在每个方法 ...

  10. Figma 学习笔记 – Comment

    步骤 按 c 键 -> 点击区域 -> 写 comment -> post 它不仅仅在 design 的 page 可以写 comment 哦, 在预览 prototype 页面也是 ...