文章目录
- 1. SecurityContextHolder 上下文持有器
- 2. ConfigAttribute 存储与安全系统相关的配置属性
- 3. GrantedAuthority 权限封装类
- 4. RoleHierarchy 角色层次结构获取
- 5. AuthenticatedPrincipal 获取主体属性
- 6. ObjectPostProcessor 对象初始化
- 7.Authentication 认证
- 7.1 ClientRegistration 客户端注册OAuth 2.0或OpenID Connect 1.0提供者的表示。
- 7.2 OAuth2Token OAuth2秘钥
- 7.3 Authentication 身份验证主体的令牌
- 7.4 UserDerails 核心用户信息
- 7.5 AuthenticationManager 认证管理器
- 7.6 UserCache UserDetails对象的缓存
- 7.7 UserDetailsService 加载用户特定数据的核心接口
- 7.8 AuthenticationProvider
- 7.9 AbstractOAuth2AuthorizationGrantRequest 授权请求
- 7.10 OAuth2UserService 从UserInfo端点获取终端用户属性
- 7.11 GrantedAuthoritiesMapper 加载权限的mapper
- 7.12 UserDetailsChecker 用户信息检查
- 8.鉴权
1. SecurityContextHolder 上下文持有器
内部封装一个SecurityContextHolderStrategy
(一种针对线程存储安全上下文信息的策略),通过配置文件初始化对应的策略,以达到获取和设置上下文的目的(SecurityContext)
1.1 SecurityContextHolderStrategy 针对线程存储安全上下文信息的策略
- ThreadLocalSecurityContextHolderStrategy:利用
ThreadLocal
来存储一个SecurityContext
- InheritableThreadLocalSecurityContextHolderStrategy:利用
InheritableThreadLocal
来存储SecurityContext
,InheritableThreadLocal
和ThreadLocal
的区别在于子线程获取出来的内容和父线程的一致。即可以在父线程和子线程中传递参数。 - GlobalSecurityContextHolderStrategy:全局策略,维护一个全局的
SecurityContext
变量,不安全,不推荐使用。 - ListeningSecurityContextHolderStrategy:内部封装一个
SecurityContextHolderStrategy
变量,保存SecurityContext
也是保存在这个变量中。在这个基础上还封装了SecurityContextChangedListener
集合,在调用clearContext
和setContext
方法时会调用SecurityContextChangedListener
的方法进行消息发布、通知
1.2 SecurityContextChangedListener 上下文变更监听器
这是一个函数式接口,Spring Security
并没有提供实现类,用户可以根据需求进行扩展。
1.3 SecurityContext 接口定义与当前执行线程关联的最小安全信息。
这个接口主要是封装Authentication
并有get
、set
方法的上下文
2. ConfigAttribute 存储与安全系统相关的配置属性
-
ConfigAttribute
:只有一个getAttribute
方法,返回值为String -
SecurityConfig
: 将ConfigAttribute存储为字符串。并提供这个字符串的获取方法等 -
Jsr250SecurityConfig
:适用于JSR 250注释属性的安全配置。/** * Security config applicable as a JSR 250 annotation attribute. * * * <pre> * * 适用于JSR 250注释属性的安全配置。 * </pre> * @author Ryan Heaton * @since 2.0 */ public class Jsr250SecurityConfig extends SecurityConfig { public static final Jsr250SecurityConfig PERMIT_ALL_ATTRIBUTE = new Jsr250SecurityConfig(PermitAll.class.getName()); public static final Jsr250SecurityConfig DENY_ALL_ATTRIBUTE = new Jsr250SecurityConfig(DenyAll.class.getName()); public Jsr250SecurityConfig(String role) { super(role); } }
-
PostInvocationAttribute
和PreInvocationAttribute
两个接口都没有任何属性,分别是@PostFilter和@PostAuthorize注解、@PreFilter和@PreAuthorize注解创建的属性的标记接口 -
AbstractExpressionBasedMethodConfigAttribute
:包含过滤和授权表达式元数据,用于基于Spring-EL的访问控制。用于方法调用前或后调用阶段的基类。过滤器或授权表达式可以为空,但不能同时为空。注意:这个类虽然重写了父类的getAttribute
方法,但固定返回null,即没有使用这个方法。 -
PreInvocationExpressionAttribute:继承父类方法的同时内部封装了一个
filterTarget
字符串。 -
PostInvocationExpressionAttribute:重写了
toString
方法
3. GrantedAuthority 权限封装类
- GrantedAuthority:只有一个
getAuthority
方法,可以获取权限字符串 - SwitchUserGrantedAuthority:内部封装一个
role
字符串和一个Authentication
对象 - JaasGrantedAuthority:内部封装一个
role
字符串和一个Principal
对象 - SimpleGrantedAuthority:内部封装一个
role
字符串 - OAuth2UserAuthority:可能与OAuth2User相关联的GrantedAuthority。内部封装一个权限字符串和一个属性map
- OidcUserAuthority:可能与一个OidcUser相关联的GrantedAuthority。在父类的基础上封装一个
OidcIdToken
和一个OidcUserInfo
4. RoleHierarchy 角色层次结构获取
该类定义了用于各种访问检查组件的角色层次结构,层次定义是使用 > 符号进行定义,例如:
//意思是Student权限拥有Study权限,Study权限拥有English权限,English权限拥有Paragraph权限,推理得,如果一个人有Student这个角色,那他同时就拥有了Student、Study、English、Paragraph权限
"Student > Study > English > Paragraph"
- RoleHierarchy:接口定义获取从属权限的方法,即传入一个授权集合,返回这个授权集合的所有从属权限。
- NullRoleHierarchy:什么都不干,传入什么就返回什么。
- RoleHierarchyImpl:利用 > 符号进行权限风格,定义从属关系(层级结构),即上面讲到的结构。
5. AuthenticatedPrincipal 获取主体属性
- AuthenticatedPrincipal:接口只提供一个获取主体名称的方法。
public interface AuthenticatedPrincipal {
/**
* Returns the name of the authenticated <code>Principal</code>. Never
* <code>null</code>.
*
* <p>
* 返回经过身份验证的主体的名称。 不为空。
* </p>
* @return the name of the authenticated <code>Principal</code>
*/
String getName();
}
- Saml2AuthenticatedPrincipal:
AuthenticatedPrincipal
的Saml2表示。这个接口提供了四个默认方法,具体的逻辑交给子类实现。 - DefaultSaml2AuthenticatedPrincipal:
Saml2AuthenticatedPrincipal
的默认实现,封装name
、attributes
和registrationId
- OAuth2AuthenticatedPrincipal:与OAuth 2.0令牌关联的主体,接口可以获取token属性、权限集合等。
- OAuth2User:在OAuth 2.0提供者中注册的用户主体的表示形式
- DefaultOAuth2User: OAuth2User的默认实现。除了获取主体名称以外,还提供了属性Map、权限集合、以及在属性Map中对应主体名称的key(以便
getName
方法获取name
) - OidcUser:使用OpenID Connect 1.0提供程序注册的用户主体的表示形式。在父类的基础上提供
getClaims
、getUserInfo
、getIdToken
三个方法 - DefaultOidcUser:
OidcUser
的默认实现。封装OidcIdToken
和OidcUserInfo
- DefaultOAuth2AuthenticatedPrincipal:包装OAuth 2.0令牌属性的域对象。封装token属性、权限集合、主体名称。
- OAuth2IntrospectionAuthenticatedPrincipal:内部封装一个
DefaultOAuth2AuthenticatedPrincipal
,所有操作都是基于这个DefaultOAuth2AuthenticatedPrincipal
6. ObjectPostProcessor 对象初始化
- ObjectPostProcessor:允许初始化对象。 通常,这用于调用Aware方法。InitializingBean.afterPropertiesSet(),并确保调用了DisposableBean.destroy()。
- AutowireBeanFactoryObjectPostProcessor: 允许注册对象来参与AutowireCapableBeanFactory对Aware方法、InitializingBean.afterPropertiesSet()和DisposableBean.destroy()的后处理。
- CompositeObjectPostProcessor:组合模式,内部封装了ObjectPostProcessor集合,遍历执行集合里每一个
ObjectPostProcessor
的postProcess
方法。
7.Authentication 认证
7.1 ClientRegistration 客户端注册OAuth 2.0或OpenID Connect 1.0提供者的表示。
这个类封装了很多Oauth2使用的信息,例如scope
、clientId
、clientSecret
等等
7.2 OAuth2Token OAuth2秘钥
- OAuth2Token:提供获取token、过期时间、令牌发出时间等属性获取接口
- AbstractOAuth2Token:对
OAuth2Token
的实现 - OAuth2AccessToken:用户的访问令牌,包括
token
的值和scope
列表 - OAuth2RefreshToken:
token
刷新令牌 - OidcIdToken:
OidcIdToken
是一个安全令牌,它包含关于授权服务器对终端用户进行身份验证的“claims”。
7.3 Authentication 身份验证主体的令牌
这个类及其下属类是各个令牌的表现方式,大多都只是针对不同功能简单的封装不同的参数
7.4 UserDerails 核心用户信息
UserDetails
提供用户的核心信息,其中User
类是最基础的,里面封装了用户的各个信息。而MutableUser
的内部封装了一个UserDetails
和一个password
,操作都是基于内部分UserDetails
,为什么在这个类里面单独封装一个password呢?可能是因为User
类实现了CredentialsContainer
接口,而这个接口是为了删除敏感数据,因此在User
类中将password
置空了。而这个类单独封装一个password
和一个UserDetails
就既可以保存password
也可以实现去除敏感数据
7.5 AuthenticationManager 认证管理器
AuthenticationManager
提供认证方法,传入Authentication
类,如果认证成功,则返回一个完全填充的Authentication
,不成功则返回null
- NoOpAuthenticationManager:这是
AbstractSecurityInterceptor
的内部类,调用这个类的authenticate
方法直接抛错 - ResolvingAuthenticationManager:这是
JwtIssuerAuthenticationManagerResolver
的内部类,是针对BearerTokenAuthenticationToken
的一个AuthenticationManager
,主要逻辑是从token中取出issuer
,再通过AuthenticationManagerResolver
解析出authenticationManager
并利用这个authenticationManager
进行认证 - ProviderManager:内部封装一个
AuthenticationProvider
集合和一个AuthenticationManager
作为父管理器,先迭代判断每一个AuthenticationProvider
,如果有认证成功的,返回完整信息,如果都不成功并且抛出的是AuthenticationException
,那么会执行父管理器的authenticate
方法判断认证是否成功。
7.6 UserCache UserDetails对象的缓存
- SpringCacheBasedUserCache:利用spring自带的
cache
来完成UserDetails
的缓存 - NullUserCache:什么都没做
7.7 UserDetailsService 加载用户特定数据的核心接口
- UserDetailsPasswordService:用于修改
UserDetails
密码的API。 - UserDetailsManager:提供
创建用户
、修改用户
、删除用户
、修改密码
、判断用户是否存在
等方法的接口 - InMemoryUserDetailsManager:
UserDetailsManager
的非持久实现,它是由一个内存映射支持的测试类,一般生产并不使用这个 - ReactiveUserDetailsServiceAdapter:
WithUserDetailsSecurityContextFactory
的内部类,内部封装一个ReactiveUserDetailsService
- CachingUserDetailsService:基于
UserCache
实现UserDetails
存储。 - UserDetailsServiceImpl:内部封装一个
UserRepository
- JdbcDaoImpl:使用
JDBC
查询从数据库中检索用户详细信息(用户名、密码、启用标志和权限)。
7.8 AuthenticationProvider
7.9 AbstractOAuth2AuthorizationGrantRequest 授权请求
OAuth 2.0权限授予请求的基本实现,该请求持有权限授予凭据,并在向授权服务器的令牌端点发起请求时使用。可以理解为我们向controller
层请求的request
请求。这个类的子类要分两部分来理解。
- 第一类:请求类,
OAuth2PasswordGrantRequest
、、OAuth2ClientCredentialsGrantRequest
、OAuth2AuthorizationCodeGrantRequest
、JwtBearerGrantRequest
、OAuth2RefreshTokenGrantRequest
,前三个类分别是密码模式(password)
、客户端模式(CLIENT_CREDENTIALS)
、授权码模式(AUTHORIZATION_CODE)
请求时携带的请求参数,后两个类是grat-type
为刷新token(REFRESH_TOKEN)
和JWT(JWT_BEARER)
的请求封装类,而四大授权模式中的隐式授权模式(IMPLICIT)
并没有在此定义的原因应该是因为官方并不建议使用这种模式,因为在HTTP重定向中返回访问令牌(而不确认客户端已接收到令牌)存在固有风险 - 第二类:返回类:我们可以看到和上述五个类平级的还有一个
OAuth2AccessTokenResponseClient
类,这个类及其子类是封装的不同模式的不同返回封装类,OAuth2AccessTokenResponseClient
是一个函数式接口,接收一个AbstractOAuth2AuthorizationGrantRequest
的子类的入参,返回OAuth2AccessTokenResponse
,其下属子类便是对不同模式的返回值的封装,大致类容是根据不同模式的请求封装requestEntity
并发送请求到具体端点,然后封装OAuth2AccessTokenResponse
并返回。
7.10 OAuth2UserService 从UserInfo端点获取终端用户属性
OAuth2UserService
是一个函数式接口,只包含一个loadUser
方法,
- DelegatingOAuth2UserService:内部包含一个
OAuth2UserService
集合,每个OAuth2UserService
都有机会加载一个OAuth2User
,并返回第一个非空的OAuth2User
- OidcUserService:内部包含一个
OAuth2UserService
,默认是DefaultOAuth2UserService
,利用这个OAuth2UserService
的loadUser
加载并封装信息返回 - DefaultOAuth2UserService:默认利用
OAuth2UserRequestEntityConverter
转换RequestEntity
并发送请求来加载用户信息并返回
7.11 GrantedAuthoritiesMapper 加载权限的mapper
- SimpleAuthorityMapper:简单的一对一 GrantedAuthoritiesMapper,它允许权限名称的大小写转换和添加字符串前缀(默认为ROLE_)。
- RoleHierarchyAuthoritiesMapper:利用
RoleHierarchy
来获取用户权限 - NullAuthoritiesMapper:什么都不做,直接返回原有权限
7.12 UserDetailsChecker 用户信息检查
用来检查用户信息是否有问题,本质都是调用UserDetails
类里的方法进行判断。
- DefaultPostAuthenticationChecks:
AbstractUserDetailsAuthenticationProvider
类的内部类,负责后置检查用户信息,这个类检查了用户密码是否过期 - DefaultPreAuthenticationChecks:
AbstractUserDetailsAuthenticationProvider
类的内部类,负责前置检查用户信息,这个类检查了用户账号是否锁定、账号是否启用、账号是否过期 - AccountStatusUserDetailsChecker:检查了用户账户是否锁定、用户是否启用、用户账号是否过期、用户密码是否过期
8.鉴权
未完待续