Spring Security(1):认证和授权的核心组件介绍及源码分析
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方式的安全框架。它包括认证(Authentication)和授权(Authorization)两个部分。
用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。用户授权指的是验证某个用户是否有权限执行某个操作。
一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。 spring security的主要核心功能为认证和授权,所有的架构也是基于这两个核心功能去实现的。
认证的核心组件:
[AuthenticationManager] 是一个接口,是认证方法的入口,定义了如何认证,接收一个Authentication对象作为参数。
[ProviderManager] 是AuthenticationManager的一个默认实现,但它并不用来处理身份认证,而是委托给配置好的AuthenticationProvider。在ProviderManager的authenticate方法中,会轮训成员变量List<AuthenticationProvider> providers。该providers中如果有一个AuthenticationProvider的supports函数返回true,那么就会调用该AuthenticationProvider的authenticate函数认证,如果认证成功则整个认证过程结束。如果不成功,则继续使用下一个合适的AuthenticationProvider进行认证,只要有一个认证成功则为认证成功。
[AuthenticationProvider] 是一个接口,ProviderManager实际上把认证过程委托给了AuthenticationProvider对象(实际上是一个List)来处理。AuthenticationProvider的实现类有很多,如:
DaoAuthenticationProvider (extends AbstractUserDetailsAuthenticationProvider):最常用的认证方式,通过UserDetailsService对UserDetails认证。
AnonymousAuthenticationProvider: 用于匿名身份认证,匿名用户名和权限使用默认值为anonymousUser,ROLE_ANONYMOUS
[Authentication] 是一个接口,它定义存储用户的Principal(用户信息),Credentials(密码),Authority(权限)等信息。它将提供这些信息给AuthenticationManager(AuthenticationProvider的各种实现类)进行验证。验证成功后,返回一个认证成功的Authentication的实现类的对象。Authentication的实现类也有很多,并且和AuthenticationProvider对应, 如:
DaoAuthenticationProvider -> UsernamePasswordAuthenticationToken
AnonymousAuthenticationProvider -> AnonymousAuthenticationToken
[UserDetails] 是一个接口,定义了认证所需的必要信息,包括用户名,密码,权限,有效性等。在实际使用里,(比用JPA)通过定义User实体类与DB中的User表和Role表映射实现UserDetails接口。也可以使用框架的User实现类来构造User,比如使用AuthenticationManagerBuilder中的inMemoryAuthentication()方法或jdbcAuthentication()方法获取InMemoryUserDetailsManagerConfigurer或JdbcUserDetailsManagerConfigurer对象来构造。
[SecurityContextHolder] & [SecurityContext] SecurityContextHolder是SecurityContext的存放容器,默认使用ThreadLocal存储,意味SecurityContext在相同线程中的方法都可用。由于SecurityContext中存放有Authentication信息,因此我们可以通过用这种方式在Security上下文中拿到User信息。如:
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
String username = ((UserDetails)principal).getUsername();
} else {
String username = principal.toString();
}
以上就是各个接口的意义及关系,认证中其实最重要的就是authenticate()方法的实现。上面也说到,AuthenticationManager把该方法委托给AuthenticationProvider来做,接下来就以AuthenticationProvider的一个最常用的实现类DaoAuthenticationProvider来叙述以下认证过程(具体代码可以从AbstractUserDetailsAuthenticationProvider.authenticate()开始看):
(1)从request中拿到username和password,存到一个UsernamePasswordAuthenticationToken(Authentication的接口实现类)对象中
(2)开始调用AbstractUserDetailsAuthenticationProvider.authenticate()方法
(3)拿到UsernamePasswordAuthenticationToken的username
(4)调用DaoAuthenticationProvider.retrieveUser(),用步骤3的username,调用UserDetailsService.loadUserByUsername()方法拿到User对象(UserDetails的接口实现类)
(5)检查步骤4中User对象的有效性(enabled,expired,locked)
(6)调用DaoAuthenticationProvider.additionalAuthenticationChecks(),比较UsernamePasswordAuthenticationToken的password和UserDetails的password(都是encoded),一致则通过
(7)调用AbstractUserDetailsAuthenticationProvider.createSuccessAuthentication()修改和完善UsernamePasswordAuthenticationToken信息,比如从UserDetails拿到的Authorities信息
(8)返回UsernamePasswordAuthenticationToken
授权的核心组件:
[AccessDecisionManager] 是一个接口,定义了在授权时如何决策的方法,具体的实现类有3个:AffirmativeBased (一票通过) ,ConsensusBased (少数服从多数),UnanimousBased (一票反对)。其中,一票通过是默认的决策。
[AbstractAccessDecisionManager] 从这个抽象类可以看出,决策的依据是是选票(Voter)的List集合。
[AccessDecisionVoter] 是一个接口,定义了vote方法,它的实现类也有很多,比如:
AuthenticatedVoter:比如某个用户对某个资源的访问是isAuthenticated()(即认证用户),该投票就通过
RoleVoter:比如某个用户对某个资源的访问是hasAnyRole("xxx")或hasRole("xxx")(即有该Role的用户),该投票就通过
我们以AffirmativeBased为例子看一下授权过程:
(1)调用AffirmativeBased.decide()方法
(2)轮训成员变量List<AccessDecisionVoter<? extends Object>> decisionVoters(在父级方法AbstractAccessDecisionManager中),如果有voter中有一个是ACCESS_GRANTED(1),则授权通过。
Spring Security(1):认证和授权的核心组件介绍及源码分析的更多相关文章
- Spring Security,没有看起来那么复杂(附源码)
权限管理是每个项目必备的功能,只是各自要求的复杂程度不同,简单的项目可能一个 Filter 或 Interceptor 就解决了,复杂一点的就可能会引入安全框架,如 Shiro, Spring Sec ...
- spring事务概念与获取事务时事务传播行为源码分析
一.事务状态:org.springframework.transaction.TransactionStatus isNewTransaction 是否是新事务 hasSavepoint 是否有保存点 ...
- 学习Spring Security OAuth认证(一)-授权码模式
一.环境 spring boot+spring security+idea+maven+mybatis 主要是spring security 二.依赖 <dependency> <g ...
- Spring Security(3):配置与自动配置的介绍及源码分析
基于注解的配置(Java Configuration)从Spring Security 3.2开始就已经支持,本篇基于Spring boot注解的配置进行讲解,如果需要基于XML配置(Security ...
- Spring AOP介绍及源码分析
转自:http://www.uml.org.cn/j2ee/201301102.asp 软件开发经历了从汇编语言到高级语言和从过程化编程到面向对象编程:前者是为了提高开发效率,而后者则使用了归纳法,把 ...
- Spring Boot启动命令参数详解及源码分析
使用过Spring Boot,我们都知道通过java -jar可以快速启动Spring Boot项目.同时,也可以通过在执行jar -jar时传递参数来进行配置.本文带大家系统的了解一下Spring ...
- 最简单易懂的Spring Security 身份认证流程讲解
最简单易懂的Spring Security 身份认证流程讲解 导言 相信大伙对Spring Security这个框架又爱又恨,爱它的强大,恨它的繁琐,其实这是一个误区,Spring Security确 ...
- Spring Cloud实战 | 第九篇:Spring Cloud整合Spring Security OAuth2认证服务器统一认证自定义异常处理
本文完整代码下载点击 一. 前言 相信了解过我或者看过我之前的系列文章应该多少知道点我写这些文章包括创建 有来商城youlai-mall 这个项目的目的,想给那些真的想提升自己或者迷茫的人(包括自己- ...
- Spring Security 接口认证鉴权入门实践指南
目录 前言 SpringBoot 示例 SpringBoot pom.xml SpringBoot application.yml SpringBoot IndexController SpringB ...
随机推荐
- C++ ---释放内存(new和delete)
C++ ---释放内存(new和delete) C++动态分配和释放内存 @c.biancheng.net/view/206.html -------------------------------- ...
- Java类的调用(实现数组排序和遍历输出)
两个类文件: Test1.java /** *同一个src下的两个类,主类在这里,调用另一个文件里的Public类 */ import java.lang.*; public class Test1 ...
- Java并发包--线程池原理
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509954.html 线程池示例 在分析线程池之前,先看一个简单的线程池示例. 1 import jav ...
- exception about Kernel Panic // dirperm1 breaks the protection by the permission bits on the lower branch
问题描述: 1. K8S集群有一个worker,经常磁盘满,然后导致服务异常. 2. 查看/var/log/syslog, 发现非常多的异常如下: 1568405.455565] docker0: p ...
- 2019EC-Final参赛总结
本来想发知乎上的,后来发现太长就放这好了23333 没写过这种东西,所以写得比较混乱&流水账 以下内容均为我的个人视角XD 赛前 在车上的时候,红太阳跟我们说他头晕(虽然他好像每场比赛都头 ...
- Educational Codeforces Round 39 (Rated for Div. 2) 946E E. Largest Beautiful Number
题: OvO http://codeforces.com/contest/946/problem/E CF 946E 解: 记读入串为 s ,答案串为 ans,记读入串长度为 len,下标从 1 开始 ...
- 013_Linux驱动之_poll机制
1. 功能:poll的机制与select相似,与select在本质上没有多大差别.管理多个描写叙述符也是进行轮询,依据描写叙述符的状态进行处理,可是poll没有最大文件描写叙述符数量的限制. 2. 技 ...
- 四十九. Zabbix报警机制 、 Zabbix进阶操作 、 监控案例
案例1:实现Zabbix报警功能 案例2:Zabbix自动发现 案例3:Zabbix主动监控 案例4:拓扑图与聚合图形 案例5:自定义监控案例 1 案例1:实现Zabbix报警功能 1.1 问题 沿用 ...
- python 比较运算符
x == y x < y x <= y x >= y x != y x is y x is not y x in y x not in y >>> "f ...
- appium测试android环境搭建(win7)
第一步:安装appium 1. 下载并安装Node.js(地址:https://nodejs.org/download/) 2. 下载git, 并且配置环境变量:(之前没有配置git, 报错找不到gi ...