Spring Security 主要类解释

用户头像
哈库拉玛塔塔
关注
发布于: 2020 年 09 月 13 日

参考出处

老徐Spring Security(一)--Architecture Overview](https://www.cnkirito.moe/spring-security-1/)

SecurityContextHolder



SecurityContextHolder 用来保存安全上下文,简单理解就是登陆的用户信息。包括用户是谁,角色权限等。它是通过 ThreadLocal 保存认证信息的,那么就意味着它与线程绑定。Spring Security 在用户登录时自动绑定认证信息到当前线程,用户退出时,自动清除当前线程的认证信息,这一前提是我们是在 web 场景下使用 Spring Security,而如果是 Swing 程序,需要替换 SecurityContextHolder 的策略。

val principal = SecurityContextHolder.getContext().authentication.principal
val username = if(principal is UserDetails){
principal.username
}else{
principal.toString()
}



Authentication



public interface Authentication extends Principal, Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
Object getCredentials();
Object getDetails();
Object getPrincipal();
boolean isAuthenticated();
void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}
  1. Authentication 是一个接口,直接继承了 PrincipalSerializable,而 Principal 是位于 java.security 包中的,Authentication 又是 Spring Security 中的接口,所以 Authentication 是在 Spring Security 中最高级别的身份/认证的抽象了。

  2. Authentication 中的方法,我们可以看到有权限集合,密码,用户细节信息,用户信息,是否认证。

- getAuthorities() ,权限信息集合

- getCredentials(),密码信息,用户输入的密码字符串,在认证过后通常会被移除

- getDetails(),细节信息,web 应用中通常为 WebAuthenticationDetails,记录了访问者的 IP 和 sessionId 的值

- getPrincipal(),最最重要的身份信息,大部分情况下返回的是 UserDetail 接口的实现类。

- isAuthenticated(),是否被认证

认证流程

  1. 用户名和密码过滤器获取到,封装成 Authentication,通常情况下是 UsernamePasswordAuthenticationToken 这个实现类

  2. AuthenticationManager 身份管理器负责验证这个 Authentication,简单理解为看看账号密码是否正确

  3. 认证成功后,AuthenticationManager 身份管理器返回一个包含权限、身份信息的 Authentication 实例。不过密码通常会被移除掉

  4. SecurityContextHolder 持有该 Authentication 的实例

AuthenticationManager

AuthenticationManagerProviderManagerAuthenticationProvider 这三者经常会把我们搞得晕头转向,这里我们梳理一下。



  • AuthenticationManger 是一个接口,它是认证功能的核心接口,也是发起认证的出发点,他之所以是接口的原因是,我们通常会是用户名+密码登录,但也会有手机号+密码,邮箱+密码等,甚至再抽象一点,指纹,虹膜都可以,所以 AuthenticationManager 是一个接口。

  • ProviderManager 是一个,它就是上面说的 AuthenticationManager 的一个实现类,那么它自然而然的就是来实现对不同的登录方式认证的逻辑,但这里需要说一下的是,个人的理解我们需要把上面说到的用户名+密码、手机号+密码、邮箱+密码这三种方式归为一个大类,或者说对应一个账号密码的 ProviderManager,而像指纹、虹膜等又可以归为另一个大类即生物特征的 ProviderManager

  • AuthenticationProvider 是大类中的小类认证方式,在 ProviderManager 类中内部会维护一个 List<AuthenticationProvider> 列表,存放多种认证方式,其实这就是委托者模式(Delegate)。



ProviderManager 中的整个认证过程其实就是,按照 List<AuthenticationProvider> 依次去认证,认证成功就直接返回,认证失败的话就会继续下一个 AuthenticationProvider,如果全都无法认证,那 ProviderManager 会抛出一个 ProviderNotFoundException 的异常。

DaoAuthenticationProvider

这是一个最常用的 AuthenticationProvider,根据类型我们能猜出来大概,这是一个从数据库查出数据库,来进行认证的一个实现。



在不讨论框架的情况下,我们的思路流程基本都是,用户前台提交用户名和密码,而数据库保存了用户名和密码,认证就是用前台提交的用户名去数据库找到对应的用户名以及密码,在对比密码是否相同或就可以了。



在 Spring Security 中前台提交的用户名和密码,被封装成了 UsernamePasswordAuthenticationToken,根据用户名加载用户的功能则交给了 UserDetailsService,在 DaoAuthenticationProvider 中还有一个 retrieveUser 方法,虽然有两个参数,但是我们可以可以只看第一个参数 username,整个方法会返回一个 UserDetails。然后还剩下密码的对比,这个交由 additionalAuthenticationChecks 方法来进行,它的逻辑是如果认证失败就抛出异常,然后就是默认通过,因为他的方法返回值是 void

UserDtails 与 UserDetailsService

UserDetails 接口代表了最详细的用户信息,它与 Authentication 接口很类似,需要注重注意的是 AuthenticationgetCredentials()UserDetail 中的 getPassword() 在理解上不一样,前者是用户提交的密码凭证(可以理解为只是一个凭证,还不知道它是否是正确的密码),而后者是用户正确的密码。Authentication 中的 getAuthorities()实际上是由 UserDetailsgetAuthorities() 传递而形成的。



UserDetailsServiceAuthenticationProvider 的区别其实很简单,UserDetailService 只是从特定的地方(一般是数据库)加载用户信息,然后就没了。



用户头像

哈库拉玛塔塔

关注

还未添加个人签名 2018.09.17 加入

还未添加个人简介

评论

发布
暂无评论
Spring Security 主要类解释