1.基本配置使用

(1)创建配置类

创建一个配置类SecurityConfig继承自WebSecurityConfigurerAdapter,重写里面的configure(HttpSecurity http)这个方法,配置好需要认证的登录url,以及提交表单的url,这里除了登录url不需要认证之外,其他的url都需要认证才能访问,并且formLogin表名这是一个表单提交,loginprocessingUrl中是设置的提交登录表单的url。

@Overrideprotected void configure(HttpSecurity http) throws Exception {           .formLogin().loginPage("/authentication/require")   //指定没有认证时跳转到的认证url.loginProcessingUrl("/authentication/form")   //提交登录表单的url.and().authorizeRequests().antMatchers("/authentication/require").permitAll()              .anyRequest().authenticated().and().csrf().disable();}

(2)获取认证信息

我们需要继承一个UserDetailSevice接口并且加入到容器中,实现loadUserByUsername方法,里面的逻辑通常是从数据库查找出对应用户名的密码然后构造一个UserDetail对象,spring security会根据返回的这个带有正确用户信息的对象和前台传过来的用户名密码进行比对来判断是否认证通过。

/*** 表单登录的时候会调用loadUserByUsername来验证前端传过来的账号密码是否正确*/
@Component
public class MyUserDetailService implements UserDetailsService {private Logger logger = LoggerFactory.getLogger(MyUserDetailService.class);@Autowiredprivate PasswordEncoder passwordEncoder;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {logger.info("登录用户名===========" + username);//这里需要去数据库查询用户的账号密码来比对是否正确,以及账号是否过期等等String password = passwordEncoder.encode("123456");logger.info("数据库密码是==============" + password);return new User(username, password,true,true,true,true,AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));}
}

这样配置好的话,比如说我们访问一个一个http://localhost:8080/user的接口,那么spring security 发现配置中这个接口是需要拦截的,并且当前的请求还没有通过认证,就会重定向到loginPage设置的这个接口或者页面中去。当我们调用loginProcessingUrl这个接口去提交表单的时候,如果通过了认证,那么就会重定向到原来我们想要访问的接口中去了,如果认证不成功,那么就出现认证失败等信息。

那么对于这个过程,spring security内部的流程到底是怎样的尼?我们先通过一张图来看。

我们可以看到在spring security内部其实是通过一个过滤器链来实现认证流程的,比如说这里的UsernamePasswordAuthenticationFilter就是拦截我们通过表单提交接口提交的用户名和密码,如果是Basic提交的话,就会被BasicAuthenticationFilter拦截,最后的橙色FilterSecurityInterceptor是首先判断我们当前请求的url是否需要认证,如果需要认证,那么就看当前请求是否已经认证,是的话就放行到我们要访问的接口,否则重定向到认证页面。

2.认证流程

这里已表单提交为例,当我们提交表单时,UsernamePasswordAuthenticationFilter首先会拦截请求,而UsernamePasswordAuthenticationFilter是继承于AbstractAuthenticationProcessingFilter的,在这个抽象类中已经定义好了doFilter的方法,而里面有一个attemptAuthentication方法是由子类实现的。所以当提交表单时spring security会发现这个一个表单提交,然后就调用了UsernamePasswordAuthenticationFilter的doFilter方法

然后我们来看 UsernamePasswordAuthenticationFilter里面重写的这个方法

然后我们可以看到首先是创建了一个UsernamePasswordAuthenticationToken对象,把用户名和密码传进去,再调用了getAuthenticationManager().authentication()方法,并把 UsernamePasswordAuthenticationToken对象传进去,那么这个AuthenticationManager是什么尼,其实它是一个接口

我们这里要看的是它的实现类ProviderManager,进去找到它的authenticate方法

其实这个ProviderManager就是管理所有的Provider对象的,通过for循环遍历找到适合的provider对象来调用其authenticate方法,那么provider对象又是什么东西?其实它也是一个接口

可以看到它的实现类有很多,我们这里主要来看DaoAuthenticationProvider这个实现类,但是在这个类中并没有找到authenticate方法,那么我们来它的父类AbstractUserDetailAuthenticationProvider里面来看下

里面调用了一个子类实现的方法,我们看这个子类的这个方法l

里面拿到我们之前加入到容器中的userDetailService然后调用loadUserByUsername方法拿到我们包含数据库用户信息的UserDetail对象,并且捕获用户名找不到等异常,所以这个方法就是来获取我们之前定义的userDetailService返回的UserDetail。

回到其父类中去,父类拿到了UserDetail对象,对这个对象进行了一系列的判断

首先我们来看下前置判断

里面就是调用了UserDetail对象一些实现方法进行判断,比如说账户是否锁定,账户是否能用,账户是否过期的判断,判断通过后来到了密码判断

在判断了密码是否正确之后,后置判断就是来判断密码是否过期了,

前置判断判断账户异常问题,然后到密码判断,最后到密码是否过期判断,因为你登录先看你账户是否有异常才能,有异常的话就不进行密码判断了,密码正确也要看密码是够过期 ,所以这三个操作合乎常理。

判断都没问题之后,最后返回了一个authentication对象,这里把用户名,密码,权限都传到UsernamePasswordAuthenticationToken中去,因为所有判断都没问题,这些信息都是正确的了。

3.认证结果如何在多个线程中共享?

首先,我们还是先来看一张图

当请求过来的时候都会最先经过一个叫SecurityContextPersistenceFilter的过滤器,这个过滤器的作用就是在请求经过的时候检查session中是否有认证的authentication对象,如果有的话就把它放进一个叫securityContext ,然后再交给securityContextHolder处理

看一下securityContext

它是一个接口,由子类SecurityContextImpl实现,里面就是一个authentication属性,所以它的作用就是包装了authentication

接下来再看一下securityContextHolder

里面的getContext,clearContext方法都是使用的一个叫 SecurityContextHolderStrategy对象,点进去看一下这个对象

我们发现它又是一个接口,我们看它的实现类ThreadLocalSecurityContextHolderStrategy

里面只有一个ThreadLocal对象,放的是SecurityContext,我们知道ThreadLocal有线程隔离的作用,每一个对象在ThreadLocal中都是线程级别的。

接着我们回到securityContextpersistenceFilter中去看里面的doFilter方法

有一个loadContext方法是加载出来SecurityContext对象的,那么它是怎么加载的?点进去

它是一个接口,看它的实现类HttpSessionSecurityContextRepository

所以上面请求经过securityContextpersistenceFilter就是先从判断session是否有SecurityContext,有的话就放进当前线程中

那么响应的时候做什么?这里直接给出

那么认证成功后,是谁把认证对象放在放在当前请求中的?答案就是FilterSecurityInterceptor,FilterSecurityInterceptor会判断当前请求的url是否要拦截,要拦截的话如果当前用户没有经过认证,那么就跳转到认证页面,如果认证了就直接放行,并且把认证信息放在当前线程中。

总的流程:一个请求过来时通过各个过滤器,最后通过FilterSecurityInterceptor来判断这个请求url是否是不需要验证的,如果是
就直接访问到我们的接口api,如果不是的话,再判断当前请求线程中是否有authentication的认证对象,如果有就放行,如果没有就返回登录页面(比如这里我们设置的是登录表单的方式),来到登录页面输入账号密码登录后就会来到    UsernamePasswordAuthenticationFilter,经过一系列的操作,最后验证成功就会把认证对象authentication放进securityContext中,然后FilterSecurityInterceptor判断到当前请求线程中这个认证对象就放行,返回的时候最后会通过securityContextpersistenceFilter,判断当前线程是否有securityContext,如果有就放进session,那么下次再请求这个url的时候会首先通过securityContextpersistenceFilter这个过滤器,判断session中是否有securityContextduxiiang,如果有就放进当前请求线程中,然后最后经过FilterSecurityInterceptor时再判断当前请求线程是否有认证对象,由于最前面经过securityContextpersistenceFilter,已经从session中把认证对象放进了当前请求线程中,所以FilterSecurityInterceptor会直接放行,这样就访问到我们的接口api。

spring security执行原理流程相关推荐

  1. spring Mvc 执行原理 及 xml注解配置说明 (六)

    Spring MVC 执行原理 在 Spring Mvc 访问过程里,每个请求都首先经过 许多的过滤器,经 DispatcherServlet 处理; 一个Spring MVC工程里,可以配置多个的 ...

  2. 最简单易懂的Spring Security 身份认证流程讲解

    最简单易懂的Spring Security 身份认证流程讲解 导言 相信大伙对Spring Security这个框架又爱又恨,爱它的强大,恨它的繁琐,其实这是一个误区,Spring Security确 ...

  3. Spring Security 中的执行原理流程分析

    1.简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spr ...

  4. Spring Security 鉴权流程

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

  5. 【闲聊杂谈】深入理解Spring Security设计原理

    1.什么是Spring Security 顾名思义,Security的意思是安全,本质上就是一个很纯粹的权限管理框架,提供认证和授权两大核心功能.在目前主流的Spring生态中的项目,说到安全框架,基 ...

  6. Spring Security Oauth2 认证流程

    1.本文介绍的认证流程范围 本文主要对从用户发起获取token的请求(/oauth/token),到请求结束返回token中间经过的几个关键点进行说明. 2.认证会用到的相关请求 注:所有请求均为po ...

  7. 【深入浅出Spring原理及实战】「技术原理」Spring Security的核心功能和加载运行流程的原理分析

    SpringSecurity的架构总览 Spring Security的简介说明 Spring Security对认证.授权和常见漏洞保护提供了全方位支持.使用的版本为:Spring Security ...

  8. Spring Security原理分析

    本文来简单的分析下Spring Security 使用原理.在前面的几节中,已经对 Spring Security 有了一个比较全的使用体验了,这节我们简单的介绍下 Spring Security 基 ...

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

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

  10. Spring Security实现RememberMe功能以及原理探究

    在大多数网站中,都会实现RememberMe这个功能,方便用户在下一次登录时直接登录,避免再次输入用户名以及密码去登录,下面,主要讲解如何使用Spring Security实现记住我这个功能以及深入源 ...

最新文章

  1. 独家 | 5大冠军出炉!李开复的AI挑战赛,冠军们聊到了这么些感受
  2. 李彦宏:汽车工业面临无人驾驶百年变局
  3. c++:用顺序表实现简单的栈
  4. go python php 压力测试_pyLot 基于python的压力测试工具
  5. oracle忘记密码
  6. 发光二极管原理,理解,相关计算
  7. android h5 书,android与H5交互
  8. matlab和robotstudio,MATLAB与Robotstudio建立socket通信(初探)
  9. centOS 6.0无法运行dump指令的解决方法
  10. DOM学习之路--Mr.Ember
  11. mysql 7 for windows_Mysql 5.7 for windows 免安装版(解压版)安装和配置
  12. 模拟ArrayList扩容
  13. 代码行数、查杀 bug 数笑笑就好,技术团队的 KPI 到底怎么定?
  14. 如何使用IDEA自带的数据库连接工具连接达梦数据库,IDEA连接DM(达梦)数据库
  15. 【2023王道数据结构】【树与二叉树】通过C++实现中序遍历的非递归算法(手动入出栈)C、C++完整实现(可直接运行
  16. Approximate Message Passing vs. Sparse Bayesian Learning?
  17. sqoop import 数据同步到hive的用法
  18. 62. 丑数(剑指Offer经典题)
  19. java实现按比例缩放图片技巧
  20. mdadm 创建md 删除md步骤

热门文章

  1. 猴子都能懂的数据库范式详解
  2. 怎么解决IPA processing failed错误, 用xcode 11打包
  3. 搜索算法(DFS,BFS等)
  4. mysql union all 等效_Mysql联合查询UNION和UNION ALL的使用介绍
  5. cpu_time()函数
  6. k-d Tree及其Java实现
  7. 利用图片指纹检测高相似度图片--相似图片搜索的原理
  8. MapReduce输出结果到多个文件
  9. 离散数学复习--第一章:命题逻辑
  10. 快速突破面试算法之二分查找篇