结构总览

Spring Security所解决的问题就是安全访问控制

安全访问控制功能其实就是对所有进入系统的请求进行拦截,校验每个请求是否能够访问它所期望的资源。

根据前边知识的学习,可以通过Filter或AOP等技术来实现,

Spring Security对Web资源的保护是靠Filter实现的,所以从这个Filter来入手,逐步深入Spring Security原理。
当初始化Spring Security时,会创建一个名为SpringSecurityFilterChainServlet过滤器

类型为org.springframework.security.web.FilterChainProxy,它实现了javax.servlet.Filter,

因此外部的请求会经过此类,下图是Spring Security过滤器链结构图:

FilterChainProxy是一个代理

真正起作用的是FilterChainProxy中SecurityFilterChain所包含的各个Filter,

同时这些Filter作为Bean被Spring管理,它们是Spring Security核心,各有各的职责,

但他们并不直接处理用户的认证,也不直接处理用户的授权,

而是把它们交给了认证管理器(AuthenticationManager)决策管理器(AccessDecisionManager)进行处理,

下图是FilterChainProxy相关类的UML图示。

spring Security功能的实现主要是由一系列过滤器链相互配合完成。

下面介绍过滤器链中主要的几个过滤器及其作用:
SecurityContextPersistenceFilter 这个Filter是整个拦截过程的入口和出口(也就是第一个和最后一个拦截器),

会在请求开始时从配置好的 SecurityContextRepository 中获取 SecurityContext,

然后把它设置给SecurityContextHolder。

在请求完成后将 SecurityContextHolder 持有的 SecurityContext 再保存到配置好的 SecurityContextRepository,

同时清除 securityContextHolder 所持有的 SecurityContext;
UsernamePasswordAuthenticationFilter 用于处理来自表单提交的认证。该表单必须提供对应的用户名和密码,

其内部还有登录成功或失败后进行处理的 AuthenticationSuccessHandler 和 AuthenticationFailureHandler,这些都可以根据需求做相关改变;
FilterSecurityInterceptor  是用于保护web资源的,使用AccessDecisionManager对当前用户进行授权访问
ExceptionTranslationFilter   能够捕获来自 FilterChain 所有的异常,并进行处理。但是它只会处理两类异常:
                                                AuthenticationExceptionAccessDeniedException,其它的异常它会继续抛出。



认证流程



AuthenticationProvider

通过前面的Spring Security认证流程得知,认证管理器(AuthenticationManager)委托AuthenticationProvider完成认证工作。
AuthenticationProvider是一个接口,定义如下:

public interface AuthenticationProvider {Authentication authenticate(Authentication authentication) throws AuthenticationException;boolean supports(Class<?> var1);
}

DaoAuthenticationProvider的基类     AbstractUserDetailsAuthenticationProvider发现以下代码:

public boolean supports(Class<?> authentication) {return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}

也就是说当web表单提交用户名密码时,Spring Security由DaoAuthenticationProvider处理。



最后,我们来看一下Authentication(认证信息)的结构,

它是一个接口,我们之前提到的UsernamePasswordAuthenticationToken就是它的实现之一:

(1)Authentication是spring security包中的接口,直接继承自Principal类,而Principal是位于java.security包中的。它是表示着一个抽象主体身份,任何主体都有一个名称,因此包含一个getName()方法。
(2)getAuthorities(),权限信息列表,默认是GrantedAuthority接口的一些实现类,通常是代表权限信息的一系列字符串。
(3)getCredentials(),凭证信息,用户输入的密码字符串,在认证过后通常会被移除,用于保障安全。
(4)getDetails(),细节信息,web应用中的实现接口通常为 WebAuthenticationDetails,它记录了访问者的ip地址和sessionId的值。
(5)getPrincipal(),身份信息,大部分情况下返回的是UserDetails接口的实现类,UserDetails代表用户的详细信息,

那从Authentication中取出来的UserDetails就是当前登录用户信息,它也是框架中的常用接口之一。



UserDetailsService

1)认识UserDetailsService
现在咱们现在知道DaoAuthenticationProvider处理了web表单的认证逻辑,认证成功后既得到一个Authentication(UsernamePasswordAuthenticationToken实现),里面包含了身份信息(Principal)。

这个身份信息就是一个Object ,大多数情况下它可以被强转为UserDetails对象。
DaoAuthenticationProvider中包含了一个UserDetailsService实例,它负责根据用户名提取用户信息UserDetails(包含密码),

而后DaoAuthenticationProvider会去对比UserDetailsService提取的用户密码与用户提交的密码是否匹配作为认证成功的关键依据,

因此可以通过将自定义的UserDetailsService 公开为spring bean来定义自定义身份验证。

public interface UserDetailsService {UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

很多人把DaoAuthenticationProviderUserDetailsService的职责搞混淆,其实UserDetailsService只负责从特定的地方(通常是数据库)加载用户信息,仅此而已。

而DaoAuthenticationProvider的职责更大,它完成完整的认证流程,同时会把UserDetails填充至Authentication。

上面一直提到UserDetails是用户信息,咱们看一下它的真面目:

它和Authentication接口很类似,

比如它们都拥有username,authorities。Authentication的getCredentials()与UserDetails中的getPassword()需要被区分对待,

前者是用户提交的密码凭证,后者是用户实际存储的密码,认证
其实就是对这两者的比对。

Authentication中的getAuthorities()实际是由UserDetails的getAuthorities()传递而形成的。

还记得Authentication接口中的getDetails()方法吗?其中的UserDetails用户详细信息便是经过了AuthenticationProvider认证之后被填充的。
通过实现UserDetailsService和UserDetails,我们可以完成对用户信息获取方式以及用户信息字段的扩展。
Spring Security提供的InMemoryUserDetailsManager(内存认证),JdbcUserDetailsManager(jdbc认证)就是UserDetailsService的实现类,主要区别无非就是从内存还是从数据库加载用户。

springsecurity的工作原理相关推荐

  1. 2021年大数据ELK(十八):Beats 简单介绍和FileBeat工作原理

    全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 Beats 简单介绍和FileBeat工作原理 一.Beats 二.FileB ...

  2. 深入理解Nginx工作原理

    1 反向代理 1.1 概念 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给intern ...

  3. 高频开关电源原理_程控开关电源的工作原理

    本文介绍了开关电源的工作原理以及它的特点. 程控开关电源要要比线性电源复杂得多. 下图是典型的开关电源工作原理图. 首先对 220 V/50Hz 的 AC 输入,通过桥式整流器进行整流 储能电容对整流 ...

  4. Servlet生命周期与工作原理

    Servlet生命周期分为三个阶段: 1,初始化阶段  调用init()方法 2,响应客户请求阶段 调用service()方法 3,终止阶段 调用destroy()方法 Servlet初始化阶段: 在 ...

  5. java的工作原理你知道吗_每天用Mybatis,但是Mybatis的工作原理你真的知道吗?

    近来想写一个mybatis的分页插件,但是在写插件之前肯定要了解一下mybatis具体的工作原理吧,于是边参考别人的博客,边看源码就开干了. 核心部件:SqlSession Executor Stat ...

  6. linux网络管理原理,Linux__网络管理(物理层 数据链路层 网络层工作原理)

    千锋云计算逆战班11点后打卡 今天学习后,进行复习下,物理层 数据链路层  网络层 的工作原理 物理层关心的两件事情:1.信号 2.介质 先说信号:信号分为模拟信号和数字信号 模拟信号: 模拟信号,不 ...

  7. HDD工作原理 导图

    以上导图介绍了我们使用的 (HDD)机械硬盘的基本构造以及核心工作原理,对于大家扫盲有所帮助 参考文档: https://blog.csdn.net/yizhaoxin/article/details ...

  8. 路由和交换机工作原理

    路由器与交换机的工作原理 计算机网络往往由许多种不同类型的网络互连连接而成.如果几个计算机网络只是在物理上连接在一起,它们之间并不能进行通信,那么这种"互连"并没有什么实际意义.因 ...

  9. Google工作原理

    今天在晚上看到一个图,讲解google的工作原理,感觉写的不错.贴过来方便以后深入的研究. 转载于:https://www.cnblogs.com/muyuge/archive/2010/07/06/ ...

最新文章

  1. linux:Ubuntu入门基础
  2. 10.25T2 二维线段树
  3. python装keras_python – 在anaconda中安装keras时出错. / p KER...
  4. 软件生成目录没有图框_图纸目录和编号
  5. sun官网jdk各版本下载链接
  6. 2.1.Python字符串处理(去掉空格或者特殊字符、替换操作、查找操作、判断操作、分割合并操作、字符串文档)
  7. wince对中文字体的支持
  8. Sandy引擎学习笔记:摄影机
  9. leetcode —— 面试题 17.12. BiNode
  10. php更改html内容,请问你们怎么将html的文件的内容改变为php
  11. 介绍几款串口监控工具
  12. 微信小程序体验版(测试环境)和线上版(生产环境)发布
  13. 【本科毕业设计】基于单片机的智能家居防火防盗报警系统
  14. Vonage与华尔街英语合作为其数字教室提供助力
  15. K_A08_004 基于 STM32等单片机驱动MX1919模块按键控制直流电机正反转加减速启停
  16. 剑与家园服务器维护有公告吗,剑与家园全服1.13.2版本停服更新维护公告
  17. hypermesh闪退启动解决(最全!!!)
  18. 2021年江苏高考生物成绩查询,2021年江苏省高考生物考试说明.docx
  19. 爬虫selenium + chrome (PhantomJS)模拟浏览器 抓取京东商城为例
  20. STM32F103 CAN通信波特率的计算方法

热门文章

  1. .NET Core2.1下采用EFCore比较原生IOC、AspectCore、AutoFac之间的性能
  2. 步进电机的单双极驱动
  3. java程序如何优化--技巧总结
  4. shell注释与赋值
  5. c#params应用
  6. S3C2443时钟管理
  7. linux中find命令列举,Linux中常见find命令的使用
  8. JAVA-接口和抽象类的区别
  9. 在ASP.NET Core中获取客户端IP地址
  10. NodeJS:将指定文件夹内所有文件重命名为英文