Spring Security源码阅读

文章目录

  • 1. SecurityContextHolder 上下文持有器
    • 1.1 SecurityContextHolderStrategy 针对线程存储安全上下文信息的策略
    • 1.2 SecurityContextChangedListener 上下文变更监听器
    • 1.3 SecurityContext 接口定义与当前执行线程关联的最小安全信息。
  • 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 针对线程存储安全上下文信息的策略

Spring Security源码阅读_第1张图片

  • ThreadLocalSecurityContextHolderStrategy:利用ThreadLocal来存储一个SecurityContext
  • InheritableThreadLocalSecurityContextHolderStrategy:利用InheritableThreadLocal来存储SecurityContextInheritableThreadLocalThreadLocal的区别在于子线程获取出来的内容和父线程的一致。即可以在父线程和子线程中传递参数。
  • GlobalSecurityContextHolderStrategy:全局策略,维护一个全局的SecurityContext变量,不安全,不推荐使用。
  • ListeningSecurityContextHolderStrategy:内部封装一个SecurityContextHolderStrategy变量,保存SecurityContext也是保存在这个变量中。在这个基础上还封装了SecurityContextChangedListener集合,在调用clearContextsetContext方法时会调用SecurityContextChangedListener的方法进行消息发布、通知

1.2 SecurityContextChangedListener 上下文变更监听器

Spring Security源码阅读_第2张图片

这是一个函数式接口,Spring Security并没有提供实现类,用户可以根据需求进行扩展。

1.3 SecurityContext 接口定义与当前执行线程关联的最小安全信息。

Spring Security源码阅读_第3张图片

这个接口主要是封装Authentication并有getset方法的上下文

2. ConfigAttribute 存储与安全系统相关的配置属性

Spring Security源码阅读_第4张图片

  • ConfigAttribute:只有一个getAttribute方法,返回值为String

  • SecurityConfig: 将ConfigAttribute存储为字符串。并提供这个字符串的获取方法等

  • Jsr250SecurityConfig:适用于JSR 250注释属性的安全配置。

    /**
     * Security config applicable as a JSR 250 annotation attribute.
     *
     * 
     * 
     *     
     *     适用于JSR 250注释属性的安全配置。  
     * 
    * @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); } }
  • PostInvocationAttributePreInvocationAttribute两个接口都没有任何属性,分别是@PostFilter和@PostAuthorize注解、@PreFilter和@PreAuthorize注解创建的属性的标记接口

  • AbstractExpressionBasedMethodConfigAttribute:包含过滤和授权表达式元数据,用于基于Spring-EL的访问控制。用于方法调用前或后调用阶段的基类。过滤器或授权表达式可以为空,但不能同时为空。注意:这个类虽然重写了父类的getAttribute方法,但固定返回null,即没有使用这个方法。

  • PreInvocationExpressionAttribute:继承父类方法的同时内部封装了一个filterTarget字符串。

  • PostInvocationExpressionAttribute:重写了toString方法

3. GrantedAuthority 权限封装类

Spring Security源码阅读_第5张图片

  • GrantedAuthority:只有一个getAuthority方法,可以获取权限字符串
  • SwitchUserGrantedAuthority:内部封装一个role字符串和一个Authentication对象
  • JaasGrantedAuthority:内部封装一个role字符串和一个Principal对象
  • SimpleGrantedAuthority:内部封装一个role字符串
  • OAuth2UserAuthority:可能与OAuth2User相关联的GrantedAuthority。内部封装一个权限字符串和一个属性map
  • OidcUserAuthority:可能与一个OidcUser相关联的GrantedAuthority。在父类的基础上封装一个OidcIdToken和一个OidcUserInfo

4. RoleHierarchy 角色层次结构获取

Spring Security源码阅读_第6张图片

该类定义了用于各种访问检查组件的角色层次结构,层次定义是使用 > 符号进行定义,例如:

//意思是Student权限拥有Study权限,Study权限拥有English权限,English权限拥有Paragraph权限,推理得,如果一个人有Student这个角色,那他同时就拥有了Student、Study、English、Paragraph权限
"Student > Study > English > Paragraph"
  • RoleHierarchy:接口定义获取从属权限的方法,即传入一个授权集合,返回这个授权集合的所有从属权限。
  • NullRoleHierarchy:什么都不干,传入什么就返回什么。
  • RoleHierarchyImpl:利用 > 符号进行权限风格,定义从属关系(层级结构),即上面讲到的结构。

5. AuthenticatedPrincipal 获取主体属性

Spring Security源码阅读_第7张图片

  • AuthenticatedPrincipal:接口只提供一个获取主体名称的方法。
public interface AuthenticatedPrincipal {

   /**
    * Returns the name of the authenticated Principal. Never
    * null.
    *
    * 

* 返回经过身份验证的主体的名称。 不为空。 *

* @return the name of the authenticated Principal */
String getName(); }
  • Saml2AuthenticatedPrincipalAuthenticatedPrincipal的Saml2表示。这个接口提供了四个默认方法,具体的逻辑交给子类实现。
  • DefaultSaml2AuthenticatedPrincipalSaml2AuthenticatedPrincipal的默认实现,封装nameattributesregistrationId
  • OAuth2AuthenticatedPrincipal:与OAuth 2.0令牌关联的主体,接口可以获取token属性、权限集合等。
  • OAuth2User:在OAuth 2.0提供者中注册的用户主体的表示形式
  • DefaultOAuth2User: OAuth2User的默认实现。除了获取主体名称以外,还提供了属性Map、权限集合、以及在属性Map中对应主体名称的key(以便getName方法获取name
  • OidcUser:使用OpenID Connect 1.0提供程序注册的用户主体的表示形式。在父类的基础上提供getClaimsgetUserInfogetIdToken三个方法
  • DefaultOidcUserOidcUser的默认实现。封装OidcIdTokenOidcUserInfo
  • DefaultOAuth2AuthenticatedPrincipal:包装OAuth 2.0令牌属性的域对象。封装token属性、权限集合、主体名称。
  • OAuth2IntrospectionAuthenticatedPrincipal:内部封装一个DefaultOAuth2AuthenticatedPrincipal,所有操作都是基于这个DefaultOAuth2AuthenticatedPrincipal

6. ObjectPostProcessor 对象初始化

Spring Security源码阅读_第8张图片

  • ObjectPostProcessor:允许初始化对象。 通常,这用于调用Aware方法。InitializingBean.afterPropertiesSet(),并确保调用了DisposableBean.destroy()。
  • AutowireBeanFactoryObjectPostProcessor: 允许注册对象来参与AutowireCapableBeanFactory对Aware方法、InitializingBean.afterPropertiesSet()和DisposableBean.destroy()的后处理。
  • CompositeObjectPostProcessor:组合模式,内部封装了ObjectPostProcessor集合,遍历执行集合里每一个ObjectPostProcessorpostProcess方法。

7.Authentication 认证

7.1 ClientRegistration 客户端注册OAuth 2.0或OpenID Connect 1.0提供者的表示。

这个类封装了很多Oauth2使用的信息,例如scopeclientIdclientSecret等等

7.2 OAuth2Token OAuth2秘钥

Spring Security源码阅读_第9张图片

  • OAuth2Token:提供获取token、过期时间、令牌发出时间等属性获取接口
  • AbstractOAuth2Token:对OAuth2Token的实现
  • OAuth2AccessToken:用户的访问令牌,包括token的值和scope列表
  • OAuth2RefreshTokentoken刷新令牌
  • OidcIdTokenOidcIdToken是一个安全令牌,它包含关于授权服务器对终端用户进行身份验证的“claims”。

7.3 Authentication 身份验证主体的令牌

请添加图片描述

这个类及其下属类是各个令牌的表现方式,大多都只是针对不同功能简单的封装不同的参数

7.4 UserDerails 核心用户信息

Spring Security源码阅读_第10张图片

UserDetails提供用户的核心信息,其中User类是最基础的,里面封装了用户的各个信息。而MutableUser的内部封装了一个UserDetails和一个password,操作都是基于内部分UserDetails,为什么在这个类里面单独封装一个password呢?可能是因为User类实现了CredentialsContainer接口,而这个接口是为了删除敏感数据,因此在User类中将password置空了。而这个类单独封装一个password和一个UserDetails就既可以保存password也可以实现去除敏感数据

7.5 AuthenticationManager 认证管理器

Spring Security源码阅读_第11张图片

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对象的缓存

Spring Security源码阅读_第12张图片

  • SpringCacheBasedUserCache:利用spring自带的cache来完成UserDetails的缓存
  • NullUserCache:什么都没做

7.7 UserDetailsService 加载用户特定数据的核心接口

Spring Security源码阅读_第13张图片

  • UserDetailsPasswordService:用于修改UserDetails密码的API。
  • UserDetailsManager:提供创建用户修改用户删除用户修改密码判断用户是否存在等方法的接口
  • InMemoryUserDetailsManagerUserDetailsManager的非持久实现,它是由一个内存映射支持的测试类,一般生产并不使用这个
  • ReactiveUserDetailsServiceAdapterWithUserDetailsSecurityContextFactory的内部类,内部封装一个ReactiveUserDetailsService
  • CachingUserDetailsService:基于UserCache实现UserDetails存储。
  • UserDetailsServiceImpl:内部封装一个UserRepository
  • JdbcDaoImpl:使用JDBC查询从数据库中检索用户详细信息(用户名、密码、启用标志和权限)。

7.8 AuthenticationProvider

7.9 AbstractOAuth2AuthorizationGrantRequest 授权请求

请添加图片描述

OAuth 2.0权限授予请求的基本实现,该请求持有权限授予凭据,并在向授权服务器的令牌端点发起请求时使用。可以理解为我们向controller层请求的request请求。这个类的子类要分两部分来理解。

  • 第一类:请求类OAuth2PasswordGrantRequest、、OAuth2ClientCredentialsGrantRequestOAuth2AuthorizationCodeGrantRequestJwtBearerGrantRequestOAuth2RefreshTokenGrantRequest,前三个类分别是密码模式(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端点获取终端用户属性

Spring Security源码阅读_第14张图片

OAuth2UserService是一个函数式接口,只包含一个loadUser方法,

  • DelegatingOAuth2UserService:内部包含一个OAuth2UserService集合,每个OAuth2UserService都有机会加载一个OAuth2User,并返回第一个非空的OAuth2User
  • OidcUserService:内部包含一个OAuth2UserService,默认是DefaultOAuth2UserService,利用这个OAuth2UserServiceloadUser加载并封装信息返回
  • DefaultOAuth2UserService:默认利用OAuth2UserRequestEntityConverter转换RequestEntity并发送请求来加载用户信息并返回

7.11 GrantedAuthoritiesMapper 加载权限的mapper

Spring Security源码阅读_第15张图片

  • SimpleAuthorityMapper:简单的一对一 GrantedAuthoritiesMapper,它允许权限名称的大小写转换和添加字符串前缀(默认为ROLE_)。
  • RoleHierarchyAuthoritiesMapper:利用RoleHierarchy来获取用户权限
  • NullAuthoritiesMapper:什么都不做,直接返回原有权限

7.12 UserDetailsChecker 用户信息检查

Spring Security源码阅读_第16张图片

用来检查用户信息是否有问题,本质都是调用UserDetails类里的方法进行判断。

  • DefaultPostAuthenticationChecksAbstractUserDetailsAuthenticationProvider类的内部类,负责后置检查用户信息,这个类检查了用户密码是否过期
  • DefaultPreAuthenticationChecksAbstractUserDetailsAuthenticationProvider类的内部类,负责前置检查用户信息,这个类检查了用户账号是否锁定、账号是否启用、账号是否过期
  • AccountStatusUserDetailsChecker:检查了用户账户是否锁定、用户是否启用、用户账号是否过期、用户密码是否过期

8.鉴权

未完待续

你可能感兴趣的:(鉴权,java)