一、前言
本章主要学习Spring Security
中基于Servlet
的认证体系结构,为后续认证执行流程源码分析打好基础。
二、身份认证机制
Spring Security
提供个多种认证方式登录系统,包括:
- Username and Password:使用用户名/密码 方式进行认证登录
- OAuth 2.0 Login:使用
OpenID Connect
和OAuth 2.0
方式进行认证登录 - CAS: 使用
CAS
企业级单点登录系统 方式进行认证登录 - SAML 2.0 Login:使用
SAML 2.0
方式进行认证登录 - Remember Me:使用记住我 方式进行认证登录
- JAAS: 使用
JAAS
方式进行认证登录 - Pre-Authentication Scenarios:使用外部机制 方式进行认证登录
- X509:使用
X509
方式进行认证登录
三、认证组件简介
Spring Security
中的认证相关组件:
-
SecurityContextHolder:安全上下文持有者,存储当前认证用户的
SecurityContext
。 -
SecurityContext :安全上下文,包含当期认证用户的
Authentication
(认证信息),从SecurityContextHolder
中获取。 -
Authentication :认证信息,用户提供的用于身份认证的凭据的输入。
-
GrantedAuthority :授予主体的权限(即角色、作用域等)。
-
AuthenticationManager :认证管理器,是一个接口,定义
Spring Security
过滤器执行身份认证的API
。 -
ProviderManager :提供者管理器,是
AuthenticationManager
的默认实现。 -
AuthenticationProvider : 认证提供者,由
ProviderManager
选择,用于执行特定类型的身份认证。 -
AuthenticationEntryPoint : 认证入口点,处理认证过程中的认证异常,比如:重定向登录页面
-
AbstractAuthenticationProcessingFilter :抽象认证处理过滤器,一个
Filter
抽象类,是身份验证的基础。
四、认证组件源码分析
4.1 SecurityContextHolder
SecurityContextHolder
(安全上下文持有者)是Spring Security
身份认证模型的核心,存储已认证用户详细信息,包含了SecurityContext
(安全上下文):
当用户认证成功后,会将SecurityContext
设置到SecurityContextHolder
中,后续流程可以用过SecurityContextHolder
静态方法直接获取用户信息:
SecurityContext context = SecurityContextHolder.getContext();// 获取 SecurityContext
Authentication authentication = context.getAuthentication();// 获取认证信息
String username = authentication.getName(); // 用户名
Object principal = authentication.getPrincipal(); // 当前用户的信息,通常是UserDetails的实例
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();// 权限
默认策略下,SecurityContextHolder
使用ThreadLocal
来存储信息,一个已认证的请求线程在过滤器阶段,会获取会话中的认证信息,并保存在当前线程的ThreadLocal
中,方便业务代码获取用户信息,线程执行完毕后,FilterChainProxy
会自动执行清除。
某些应用程序并不完全适合使用默认策略 ,因为它们使用线程有特定方式。 例如:Swing
客户端可能希望Java
中的所有线程都使用相同的SecurityContextHolder
,您可以在启动时使用策略进行配置,以指定您希望如何存储SecurityContext
。
其他应用程序可能希望由安全线程派生的线程也采用相同的安全标识。 您可以通过两种方式更改默认模式:
- 第一种是设置系统属性,通过
System.getProperty("spring.security.strategy")
读取设置系统属性。 - 第二种是在调用静态方法,通过调用
SecurityContextHolder.setStrategyName(String strategyName)
设置。
SecurityContextHolder
提供的strategyName
有以下几种:
SecurityContextHolder.MODE_GLOBAL
SecurityContextHolder.MODE_INHERITABLETHREADLOCAL
SecurityContextHolder.MODE_THREADLOCAL
大多数应用程序不需要更改默认值。
未完待续~~~~!!!!