当前位置:网站首页>Oauth2.0 Supplement
Oauth2.0 Supplement
2022-08-02 16:06:00 【zhangyu】
SecurityContextHolder
SecurityContextHolder
用于存储安全上下文(security context)的信息.当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保存在 SecurityContextHolder 中.SecurityContextHolder
默认使用ThreadLocal
策略来存储认证信息.看到ThreadLocal
也就意味着,这是一种与线程绑定的策略.- Spring Security 在用户登录时自动绑定认证信息到当前线程,在用户退出时,自动清除当前线程的认证信息.但这一切的前提,是你在web场景下使用Spring Security.
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
String username = ((UserDetails)principal).getUsername();
} else {
String username = principal.toString();
}
- getAuthentication()返回了认证信息,再次 getPrincipal() 返回了身份信息,
- UserDetails便是Spring对身份信息封装的一个接口
Authentication
package org.springframework.security.core;// <1>
public interface Authentication extends Principal, Serializable {
// <1>
Collection<? extends GrantedAuthority> getAuthorities(); //权限信息列表,默认是GrantedAuthority接口的一些实现类,通常是代表权限信息的一系列字符串.
Object getCredentials();//密码信息,用户输入的密码字符串,在认证过后通常会被移除,用于保障安全.
Object getDetails();//细节信息,web应用中的实现接口通常为 WebAuthenticationDetails,它记录了访问者的ip地址和sessionId的值.
Object getPrincipal();//最重要的身份信息,大部分情况下返回的是UserDetails接口的实现类,也是框架中的常用接口之一.
boolean isAuthenticated();
void setAuthenticated(boolean var1) throws IllegalArgumentException;
}
AuthenticationManager
初次接触 Spring Security 的朋友相信会被AuthenticationManager
,ProviderManager
,AuthenticationProvider
…这么多相似的Spring认证类搞得晕头转向,但只要稍微梳理一下就可以理解清楚它们的联系和设计者的用意.
- AuthenticationManager(接口)是认证相关的核心接口,也是发起认证的出发点,因为在实际需求中,我们可能会允许用户使用用户名+密码登录,同时允许用户使用邮箱+密码,手机号码+密码登录,甚至,可能允许用户使用指纹登录
- 所以说 AuthenticationManager 一般不直接认证,AuthenticationManager接口的常用实现类
ProviderManager
内部会维护一个List<AuthenticationProvider>
列表,存放多种认证方式,实际上这是委托者模式的应用(Delegate). - 核心的认证入口始终只有一个:AuthenticationManager,不同的认证方式:用户名+密码(UsernamePasswordAuthenticationToken),邮箱+密码,手机号码+密码登录则对应了三个 AuthenticationProvider.
// key certification sectionProviderManager源码如下:
public class ProviderManager implements AuthenticationManager, MessageSourceAware,
InitializingBean {
// 维护一个AuthenticationProvider列表
private List<AuthenticationProvider> providers = Collections.emptyList();
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
Class<? extends Authentication> toTest = authentication.getClass();
AuthenticationException lastException = null;
Authentication result = null;
// 依次认证
for (AuthenticationProvider provider : getProviders()) {
if (!provider.supports(toTest)) {
continue;
}
try {
result = provider.authenticate(authentication);
if (result != null) {
copyDetails(authentication, result);
break;
}
}
...
catch (AuthenticationException e) {
lastException = e;
}
}
// 如果有Authentication信息,则直接返回
if (result != null) {
if (eraseCredentialsAfterAuthentication && (result instanceof CredentialsContainer)) {
//移除密码
((CredentialsContainer) result).eraseCredentials();
}
//发布登录成功事件
eventPublisher.publishAuthenticationSuccess(result);
return result;
}
...
//执行到此,说明没有认证成功,包装异常信息
if (lastException == null) {
lastException = new ProviderNotFoundException(messages.getMessage(
"ProviderManager.providerNotFound",
new Object[] {
toTest.getName() },
"No AuthenticationProvider found for {0}"));
}
prepareException(lastException, authentication);
throw lastException;
}
}
ProviderManager
中的List,会依照次序去认证,认证成功则立即返回,若认证失败则返回null,下一个AuthenticationProvider会继续尝试认证,如果所有认证器都无法认证成功,则ProviderManager
会抛出一个ProviderNotFoundException异常.
Spring Security是如何完成身份认证的?
- 用户名和密码被过滤器获取到,封装成
Authentication
,通常情况下是UsernamePasswordAuthenticationToken
这个实现类. AuthenticationManager
身份管理器负责验证这个Authentication
- 认证成功后,
AuthenticationManager
身份管理器返回一个被填充满了信息的(包括上面提到的权限信息,身份信息,细节信息,但密码通常会被移除)Authentication
实例. SecurityContextHolder
安全上下文容器将第3步填充了信息的Authentication
,通过SecurityContextHolder.getContext().setAuthentication(…)方法,设置到其中.
Oauth2.0 常见异常
- UsernameNotFoundException:用户名未找到.
- BadCredentialsException:认证错误.Can be used for password errors、Incorrect verification code, etc.
- RememberMeAuthenticationException:记住我 认证错误. Often in login 记住我 选项,Error caused by this place.
- AccountStatusException:The user account status is abnormal.such as being banned.
- NonceExpiredException:Nonce过期异常.
- AuthenticationCredentialsNotFoundException:SecurityContext中不存在Authentication异常.
- AuthenticationServiceException:The authentication service is abnormal.It may be a problem with the back-end database and so on.
- ProviderNotFoundException:Provider找不到异常.由ProviderManager抛出.
- SessionAuthenticationException:Session authentication exception.Usually because the same user has multiple sessions open.
- InsufficientAuthenticationException:Insufficient authentication information exception?可能是由于 记住我 option raised.
Oauth2.0 系列文章
以下是同步到语雀的、可读性好一点,CSDN 继续看的点专栏就好.
Oauth2.0 核心篇
Oauth2.0 安全性(以微信授权登陆为例)
Oauth2.0 认证服务器搭建
Oauth2.0 添加验证码登陆方式
Oauth2.0 资源服务器搭建
Oauth2.0 自定义响应值以及异常处理
Oauth2.0 补充
边栏推荐
猜你喜欢
随机推荐
char array/string array|array pointer/pointer array/
The use of a semaphore/interprocess communication 】 【 Shared memory
unity Domain Reload & scene Reload 静态变量重置
光波导应用中的真实光栅效应
UnityAPI-Ray-Physics
我的2021回忆录
unity 和C# 一些官方优化资料
flex布局
打包项目上传到PyPI
idea同时修改相同单词
Qt | 串口通信 QSerialPort
Unity-Post Processing
Unity中事件的3种实现方法
px和em和rem的区别
JOOQ 报错 StackOverflowError
光栅区域衍射级数和效率的规范
OpenPose 命令行说明
implement tcp copa on ns3
shader 和 ray marching
剑指offer:反转链表