当前位置:网站首页>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 补充
边栏推荐
猜你喜欢
随机推荐
lua编程
优先级表和Ascll表
【Solidity智能合约基础】-- 基础运算与底层位运算
Class template/assignment operations and add operations
TypeScript
戴森球计划这个游戏牛逼
Apache ShardingSphere 5.1.2 发布|全新驱动 API + 云原生部署,打造高性能数据网关...
Google AdSense注册流程
CDH(computational Diffie-Hellman)问题以及与离散对数、DDH问题的区别
tcp transparent proxy (IP_TRANSPARENT)
【网络安全】学习笔记 --02 安全通信协议
couldn't find 'libflutter.so' --flutter
Evaluate multipath BBR congestion control on ns3
【软件测试】自动化测试selenium3
udp transparent proxy
理解:野指针,空指针,失效指针。
JOOQ 报错 StackOverflowError
泰伯效应的建模
tpproxy-tcp透明代理
unity 和C# 一些官方优化资料