本文基于 Spring Security 5.x

推荐阅读:

项目集成Spring Security

SpringSecurity 整合 JWT

一、外层-正常登陆调用

项目启动后会自动寻找 UserDetailsService 实现类;

执行 UserDetailsService 的唯一方法 loadUserByName(String username) 并返回 UserDetail 类,注意,返回的 UserDetail 是根据用户名去数据库查询到用户信息;

拿到 UserDetail 后会对 UserDetail 进行一个预检查;

预检查啥?

用户是否存在,是否被锁定等等等;

全部认证成功后会调用 AuthenticationSuccess 成功处理类,失败则调用 AuthenticationFailHandler 类;

此时对于前后端分离项目而言,调用成功处理类,通常是返回由 JWT 等生成的 token json 字符串,前台拿到返回信息后,保存 token 致本地,然后每次请求都会拼接到 head 中。

二、内层-源码级别

以访问某个项目中已有的链接为例:

http://localhost:7777/tmax/videoCategory/getAll

输入用户名、密码后点击登录按钮,首先进入 UsernamePassworkAuthenticationFilter 的父类
AbstractAuthenticationProcessingFilter 调用 doFilter() 方法,然后再执行 UsernamePasswordAuthenticationFilter 的 attemptAuthentication() 方法进行验证;

UsernamePassworkAuthenticationFilter 类,顾名思义,表单登陆过滤器,该类中重点是 attemptAuthentication() 方法:

该方法中通过 用户名+密码= 实例化一个 UsernamePasswordAuthenticationToken 的对象,作用是将用户请求的信息(用户名、密码、seeesion等)封装到该对象中,我们点击进入该对象的构造器如下图所示:

需要说明一点的是,super((Collection)null); collection 代表权限列表,在这传了一个 null 进去是因为刚开始并没有进行认证,因此用户此时没有任何权限,并且设置没有认证的信息 setAuthenticated(false)

再回到 UsernamePassworkAuthenticationFilter attemptAuthentication() 方法,可以看到方法最后调用了 getAuthenticationManager() 方法,然后就进入了 AuthenticationManager 接口的实现类 ProviderManager 中。

补充:AuthenticationManager 不包含验证用户名以及密码的功能,只是用来管理 AuthenticationProvider,所有的校验规则都是写在 AuthenticationProvider 中的;

继续走,在 ProviderManager 这个实现类中,它会调用AuthenticationProvider 接口的实现类获取用户的信息,用户的信息权限的验证就在该类中校验。

进入 ProviderManager 类后会调用 authenticate(Authentication authentication) 方法,它通过 AuthenticationProvider 实现类获取用户的登录的方式,然后会有一个 while 迭代器模式的循环遍历,检查它是否支持这种登录方式,具体的登录方式有表单登录,qq登录,微信登录等。如果最终都不支持会抛出相应的异常信息,如果支持则会进入AuthenticationProvider 接口的抽象实现类 AbstractUserDetailsAuthenticationProvider 中。

进入 AbstractUserDetailsAuthenticationProvider 类后会调用 authenticate(Authentication authentication) 方法对用户的身份进行校验,首先是判断用户是否为空,这个 user 是 UserDetail 的对象,如果为空,表示还没有认证,就需要调用 retrieveUser 方法去获取用户的信息,这个方法是抽象类 AbstractUserDetailsAuthenticationProvider 的扩展类DaoAuthenticationProvider 的一个方法。

在该扩展类的 retrieveUser 方法中调用 UserDetailsService 这个接口的实现类的 loadUserByUsername 方法去获取用户信息,而这里我自己编写了实现类 UserDetailsServiceImpl 类,在这个实现类中,我们可以编写自己的逻辑,从数据库中获取用户密码等权限信息返回。

本地 UserDetailService 实现类 UserDetailsServiceImpl:

在拿到用户的信息后,返回到 AbstractUserDetailsAuthenticationProvider 类中调用 createSuccessAuthentication(principalToReturn, authentication, user) 方法,在该方法中会调用三个参数的UsernamePasswordAuthenticationToken 构造器,不同于前面调用两个参数的,因为这里已经验证了用户的信息和权限,因此不再是给父类构造器中传null 值了,而是用户的权限集合,并且设置认证通过setAuthenticated(true)

如下是 UsernamePasswordAuthenticationToken 构造器:

此时 authorities 不再为空了。

在 UsernamePasswordAuthenticationToken 的父类中,它会检查用的权限,如果有一个为 null,表示权限没有相应的权限,抛出异常。

然后在 createSuccessAuthentication 方法返回后回到 ProvioderManager 的 authenticate 方法中返回 result,最后回到UsernamePasswordAuthenticationFilter 的刚开始进入的 attemptAuthentication 方法中返回。

attemptAuthentication() 方法中的返回,返回到哪?

再回到第一张图,UsernamePasswordAuthenticationFilter 父类 doFilter() 方法,返回值就是 authResult,如果过程中发现存在异常则执行 unsuccessfulAuthentication.onAuthenticationFailure() 方法,如果认证成功则执行 successfulAuthentication.onAuthenticationSuccess() 方法,再结合上边提到的自定义 成功/失败处理类。

最后总结

流程大致是,首先进入 UsernamePasswordAuthenticationFilter 父类 AbstractAuthenticationProcessingFilter 执行 doFilter() 方法,这个 doFilter() 方法呢执行如下:

  1. 判断当前的 filter 是否可以处理当前请求,不可以的话则交给下一个 filter 处理;
  2. 抽象方法由子类 UsernamePasswordAuthenticationFilter 实现;
  3. 认证成功后,调用 sessionStrategy.onAuthentication() 处理一些与 session 相关的方法,最后再调用认证成功处理类,主要将当前的认证放到SecurityContextHolder中;
  4. 认证失败后则调用 认证失败处理类;

习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:niceyoo

Spring Security 认证执行流程相关推荐

  1. 一个接口是如何在Keycloak和Spring Security之间执行的

    在上一篇我们对Keycloak的常用配置进行了熟悉,今天我们来对Keycloak适配Spring Security的执行流程做一个分析,简单了解一下其定制的一些Spring Security过滤器. ...

  2. 看清spring security 认证流程,自定义认证方式

    一.文献参考 Spring Security认证与授权的原理(源码分析,超详细)_Zystem-CSDN博客_springsecurity认证原理 spring security为什么这么复杂? - ...

  3. spring security认证的底层实现

    一.官方认证图 发起认证请求,请求中携带用户名.密码,该请求会被UsernamePasswordAuthenticationFilter 拦截 在UsernamePasswordAuthenticat ...

  4. Spring Security认证过程

    2019独角兽企业重金招聘Python工程师标准>>> Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一 ...

  5. 请简述Spring MVC的执行流程

    需要面试文档可S我 今天我给大家介绍一下Spring MVC的详细执行流程.我把Spring MVC的执行流程划分为三个阶段,配置阶段.初始化阶段和运行阶段. 我整理了一张完整的执行流程图,需要高清图 ...

  6. 大白话详解Spring Security认证流程

    前言 Spring Seuciry相关的内容看了实在是太多了,但总觉得还是理解地不够巩固,还是需要靠知识输出做巩固. 相关版本: java: jdk 8 spring-boot: 2.1.6.RELE ...

  7. Shiro框架:Shiro简介、登陆认证入门程序、认证执行流程、使用自定义Realm进行登陆认证、Shiro的MD5散列算法

    一.Shiro介绍: 1.什么是shiro: (1)shiro是apache的一个开源框架,是一个权限管理的框架,实现用户认证.用户授权. (2)spring中有spring security,是一个 ...

  8. Spring Security 鉴权流程

    如果对该文章感兴趣欢迎关注我的小博客 Forest,我会分享更多学习时遇到的知识 (●'◡'●) 参考资料 SpringSecurity原理剖析与权限系统设计 SpringSecurity动态鉴权流程 ...

  9. Spring Security 认证授权详解

    1.Spring Security 概述 1.1.Spring Security 简介 Spring Security 是 Spring 家族中的成员.Spring Security 基于 Sprin ...

最新文章

  1. 如何在Panel中嵌入子窗体
  2. 第三天学习Java的笔记(自增自减,赋值,比较,逻辑,三元)
  3. linux nginx svn 更新前端代码
  4. 表格存储技术方案实践及客户案例分享
  5. PHP 通过设置P3P头来实现跨域访问COOKIE
  6. axure 图片切换图片的交互_AxureRP8中实现伸缩式的图片展示交互效果
  7. Session和Cookie的学习笔记2
  8. 前端开发者必备google插件
  9. 科大讯飞交通超脑荣获 2019 年大数据应用最佳实践案例 TOP10
  10. excel字符串和单元格拼接_Excel单元格内计算式及字符串拼接实现
  11. 计算机专业自主招生有哪些学校,2019自主招生学校有哪些 自主招生考试院校名单...
  12. LayUI分页查询展示数据(SSH框架)
  13. youtube字幕下载
  14. 朋友说:能不能用python,帮我写一个“制作工资条”的自动化程序?
  15. XSS攻击的一个校内简单实例
  16. 网络服务器带宽Mbps、Mb/s、MB/s有什么区别?10M、100M到底是什么概念?
  17. Web前端开发工程师--面试要求
  18. Androidnbsp;滑动开关控件
  19. 递归算法实现二分查找
  20. 网络空间安全进入动态防御时代

热门文章

  1. [css] 如何用css实现把“我不爱996”变成“699爱不我”?
  2. 前端学习(2653):对比vue2中的实现
  3. 工作173:一级控制二级菜单的变化
  4. 前端学习(2439):jsonbin-init的使用
  5. “约见”面试官系列之常见面试题之第六十四篇之call和apply区别(建议收藏)
  6. 前端学习(1800):前端调试之清除浮动练习1
  7. 前端学习(1601):状态提升
  8. 前端学习(702):while循环
  9. [机器学习笔记]Note14--推荐系统
  10. python网格划分_在python中创建一个2d网格