AuthenticationManager是一个接口:

public interface AuthenticationManager {
Authentication authenticate(Authentication authentication)
throws AuthenticationException;
}

ProviderManager是AuthenticationManager的实现类:

public class ProviderManager implements AuthenticationManager, MessageSourceAware,
InitializingBean { ...... private List<AuthenticationProvider> providers = Collections.emptyList(); ...... public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
......
}
}

从以上代码中可以看到ProviderManager有一个List<AuthenticationProvider> providers成员变量。AuthenticationProvider也是一个接口:

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

可以看到包含两个成员函数authenticate和supports。

接下来我们看一下整个的认证过程:

认证是通过AuthenticationManager的authenticate函数实现的。也就是通过AuthenticationManager实现类ProviderManager的authenticate函数认证,ProviderManager的authenticate函数会轮训ProviderManager的List<AuthenticationProvider> providers成员变量,如果该providers中如果有一个AuthenticationProvider的supports函数返回true,那么就会调用该AuthenticationProvider的authenticate函数认证,如果认证成功则整个认证过程结束。如果不成功,则继续使用下一个合适的AuthenticationProvider进行认证,只要有一个认证成功则为认证成功。

如果上述过程没有认证成功,且该ProviderManager的成员变量AuthenticationManager parent不为null,那么会使用该parent继续认证。一般不会用到该AuthenticationManager parent,稍微留意以下即可。

另:Authentication

可以看到authenticate函数返回Authentication,Authentication是一个接口,通过该接口可以获得用户相信信息,代码:

public interface Authentication extends Principal, Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
Object getCredentials();
Object getDetails();
Object getPrincipal();
boolean isAuthenticated();
void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}

另:DaoAuthenticationProvider

<authentication-provider>默认实例化AuthenticationProvider的一个实现:DaoAuthenticationProvider。DaoAuthenticationProvider通过接口UserDetailsService的实现类从内存或DB中获取用户信息UserDetails(UserDetails十分类似Authentication,也是一个接口,但是与Authentication用途不同,不要搞混)。DaoAuthenticationProvider通过函数authenticate比较入参authentication与UserDetails是否相符,来判断用户是否可以登录。如果相符,会将获得的UserDetails中的信息补全到一个Authentication实现类,并将该实现类作为认证实体返回。以后便可以通过当前上下文的认证实体Authentication获取当前登录用户的信息。

UserDetails代码:

public interface UserDetails extends Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
String getPassword();
String getUsername();
boolean isAccountNonExpired();
boolean isAccountNonLocked();
boolean isCredentialsNonExpired();
boolean isEnabled();
}

UserDetails和Authentication区别:

接口 目的
Authentication

它存储安全实体的标识、密码以及认证请求
的上下文信息。它还包含用户认证后的信息
(可能会包含一个 UserDetails 的实例)
。通常
不会被扩展,除非是为了支持某种特定类型
的认证。

UserDetails

为了存储一个安全实体的概况信息,包含名
字、e-mail、电话号码等。通常会被扩展以支
持业务需求。

AuthenticationManager, ProviderManager 和 AuthenticationProvider的更多相关文章

  1. 【Spring】关于Boot应用中集成Spring Security你必须了解的那些事

    Spring Security Spring Security是Spring社区的一个顶级项目,也是Spring Boot官方推荐使用的Security框架.除了常规的Authentication和A ...

  2. Spring Security(三十二):10. Core Services

    Now that we have a high-level overview of the Spring Security architecture and its core classes, let ...

  3. Spring Boot中集成Spring Security 专题

    check to see if spring security is applied that the appropriate resources are permitted: @Configurat ...

  4. spring security梳理

    核心服务:AuthenticationManager,UserDetailsService和AccessDecisionManager The AuthenticationManager, Provi ...

  5. AuthenticationManager、ProviderManager

    本篇主要讲述以下几点: 1.AuthenticationManager.ProviderManager和AuthenticationProvider三者之间的关系 2.以UsernamePasswor ...

  6. spring security 配置多个AuthenticationProvider

    前言 发现很少关于spring security的文章,基本都是入门级的,配个UserServiceDetails或者配个路由控制就完事了,而且很多还是xml配置,国内通病...so,本文里的配置都是 ...

  7. Spring Security 实战干货:AuthenticationManager的初始化细节

    1. 前言 今天有个同学告诉我,在Security Learning项目的day11分支中出现了一个问题,验证码登录和其它登录不兼容了,出现了No Provider异常.还有这事?我赶紧跑了一遍还真是 ...

  8. Spring Security Filter详解

    Spring Security Filter详解 汇总 Filter 作用 DelegatingFilterProxy Spring Security基于这个Filter建立拦截机制 Abstract ...

  9. Spring Security 概念基础 验证流程

    Spring Security 概念基础 验证流程 认证&授权 认证:确定是否为合法用户 授权:分配角色权限(分配角色,分配资源) 认证管理器(Authentication Manager) ...

随机推荐

  1. CMD杀进程 例如:杀8080端口的进程

    首先:端口被占用的报错形式如下 说明8080端口被占用 解决方案一:查找pid,根据pid去任务管理器的进程中结束占用8080端口号的进程 1.首先按快捷键windows+R,在运行框里输入cmd,如 ...

  2. Hadoop入门实例——WordCount统计单词

    首先要说明的是运行Hadoop需要jdk1.6或以上版本,如果你还没有搭建好Hadoop集群,请参考我的另一篇文章: Linux环境搭建Hadoop伪分布模式 马上进入正题. 1.启动Hadoop集群 ...

  3. CodeForces 718C Sasha and Array

    线段树. 线段树维护区间矩阵和,操作都是最简单的线段树.$lazy$标记不要记录乘了几次,直接记录乘了几次之后的矩阵就可以了,不然每次下传的时候再算一遍时间复杂度会提高. #pragma commen ...

  4. Launchpad灰色图标怎么删除?重置Launchpad教程

    打开终端,第一步输入:defaults write com.apple.dock ResetLaunchPad -bool true 按下return键 第二步输入:killall Dock 按下re ...

  5. 使用navicat连接远程linux的mysql中文显示乱码的问题

    在navicat对应的连接上 右键->连接属性->高级 去掉使用mysql字符集 然后上面的编码选择 (65001)utf-8 接着打开连接  找到对应的数据库 右键  数据库属性 把编码 ...

  6. express 4.x 文件上传

    1.安装文件上传模块: npm install multiparty --save 2.在routes/index.js 中添加: // 引用模块 let multiparty = require(& ...

  7. js导航栏样式变换

    <script type="text/javascript"> $(function(){ var lis = $(".submenu").chil ...

  8. Ansible Filter

    没啥好说的. 自己看吧 http://docs.ansible.com/ansible/playbooks_filters.html

  9. WPF中TextBox的PreviewMouseLeftButtonUp事件

    当使用TextBox的PreviewMouseLeftButtonUp事件时(例如,鼠标点击进入TextBox时,清除当前的输入内容),会很意外地发现,这时候不论怎么点击都无法点击到其他控件,焦点一直 ...

  10. PHP数组关于数字键名的问题

    以下是对PHP数组数字键名的几点总结: 键名长度只能在 int 长度范围内,超过int 范围后将会出现覆盖等混乱情况 在键名长度为 int 范围内存取值时,PHP会强制将数字键名转换为 int 数值型 ...