二、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. python模块xlsxwriter使用

    1.安装 pip install XlsxWriter 2.使用 # -*- coding: utf-8 -*- from io import BytesIO import qrcode # impo ...

  2. 多队列网卡-虚拟机Linux系统设置

    多队列网卡配置 作者使用的是ubuntu 20.04,VMWARE 首先查看系统上的网卡 ip a # 查看网卡信息 查看ens33是否支持多队列网卡,如果是下图这种情况就是不支持多队列网卡. cat ...

  3. Java Web专题攻关

    servlet概念 servlet其实就是运行在服务器的一个小程序 如何去理解呢?我们访问服务器的资源包括静态资源和动态资源,其中静态资源是我们放置的模板,CSS.JS等文件,是不变的.而我们访问的动 ...

  4. Jenkins 运行pipeline 报错:A Jenkins administrator will need to approve this script before it can be us

    之前没有注意过这个问题,是因为之前运行pipeline时,默认勾选了"使用 Groovy 沙盒" 这次不小心取消了勾选导致,重新加上勾选即可

  5. 【YashanDB知识库】oracle dblink varchar类型查询报错记录

    问题单:Oracle DBLINK查询崖山DB报错 oracle服务器上ODBC安装 unixodbc安装:yum -y install unixODBC mysql 配置安装对应版本的odbc: m ...

  6. c++11 动态内存与智能指针详解

    c++ 动态内存与智能指针详解 一. 动态内存 (一)程序对象的生存期 全局对象在程序启动时分配,在程序结束时销毁. 对于局部自动对象,当我们进入其定义所在的程序块时被创建,在离开块时销毁. 局部st ...

  7. 18 Python如何操作文件?

    本篇是 Python 系列教程第 18 篇,更多内容敬请访问我的 Python 合集 1 打开文件 通常使用内置的 open(文件路径, 模式, encoding="utf-8") ...

  8. 前端使用 Konva 实现可视化设计器(22)- 绘制图形(矩形、直线、折线)

    本章分享一下如何使用 Konva 绘制基础图形:矩形.直线.折线,希望大家继续关注和支持哈! 请大家动动小手,给我一个免费的 Star 吧~ 大家如果发现了 Bug,欢迎来提 Issue 哟~ git ...

  9. Figma 学习笔记 – Align 对齐

    Figma 有几个常用的对齐方法 从左到右 1. 左对齐 Alt + A 2.左右居中对齐 Alt + H 3.右对齐 Alt + D 4.上对齐 Alt + W 5.上下居中对齐 Alt + V 6 ...

  10. 1Panel:一个现代化、开源的 Linux 服务器运维管理面板

    前言 之前有小伙伴问:Linux 服务器运维管理除了宝塔,还有其他值得推荐的管理软件吗?,今天大姚给大家分享一个现代化.开源的 Linux 服务器运维管理面板:1Panel. 项目介绍 1Panel是 ...