
介绍
Spring Security 是一个功能强大、可高度定制的 身份验证 和 访问控制 框架,是保护基于 Spring 的应用程序的事实标准
SpringSecurity 是一个面向 Java 应用程序框架,与所有的 Spring 项目一样,它可以轻松地扩展以满足定制需求
权限管理
权限管理 = 身份认证 + 授权,简称 认证授权
整体架构:
认证流程:
认证
AuthenticationManager接口,在 Spring Security 中认证是由 AuthenticationManager 来负责的,接口定义为:
// 当返回 Authentication 时,表示认证成功;当返回AuthenticationException 异常时,表示认证失败
public interface AuthenticationManager {
Authentication authenticate(Authentication var1)
throws AuthenticationException;
}AuthenticationManager 主要实现类为 ProviderManager,在 ProviderManager 中管理了众多 AuthenticationProvider 实例
在⼀次完整的认证流程中,Spring Security 允许存在多个 AuthenticationProvider ,用来实现多种认证方式,这些 AuthenticationProvider 都是由 ProviderManager 进行统⼀管理
Authentication接口,认证以及认证成功的信息主要是由 Authentication 的实现类进行保存的,接口定义如下:
public interface Authentication extends Principal, Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
Object getCredentials();
Object getDetails();
Object getPrincipal();
boolean isAuthenticated();
void setAuthenticated(boolean var1) throws IllegalArgumentException;
}
// getAuthorities 获取用户权限信息
// getCredentials 获取用户凭证信息,⼀般指密码
// getDetails 获取用户详细信息
// getPrincipal 获取用户身份信息,用户名、用户对象等
// isAuthenticated 用户是否认证成功
// `SecurityContextHolder` 类,SecurityContextHolder 用来获取登录之后用户信息Spring Security 会将登录用户数据保存在 Session 中。但是,为了使用方便, Spring Security 在此基础上还做了一些改进,其中最主要的⼀个变化就是 线程绑定
- 当用户登录成功后, Spring Security 会将登录成功的用户信息保存到 SecurityContextHolder 中。SecurityContextHolder 中的数据保存默认是通过 ThreadLocal 来实现的,使用 ThreadLocal 创建的变量只能被当前线程访问,不能被其他线程访问和修改,也就是用户数据和请求线程绑定在⼀起。
- 当登录请求处理完毕后,Spring Security 会将 SecurityContextHolder 中的数据拿出来保存到 Session 中,同时将 SecurityContexHolder 中的数据清空。以后每当有请求到来时,Spring Security 就会先从 Session 中取出用户登录数据,保存到 SecurityContextHolder 中,方便在该请求的后续处理过程中使用,同时在请求结束时将 SecurityContextHolder 中的数据拿出来保存到 Session 中,然后将 SecurityContextHolder 中的数据清空。
- 这⼀策略非常方便用户在 Controller、Service 层以及任何代码中获取当前登录用户数据。
授权
- 在 Spring Security 的授权体系中,有两个关键接口:
AccessDecisionManager和AccessDecisionVoter。
AccessDecisionManager (访问决策管理器),用来决定此次访问是否被允许。接口定义如下:
public interface AccessDecisionManager {
void decide(Authentication var1, Object var2, Collection<ConfigAttribute> var3) throws AccessDeniedException, InsufficientAuthenticationException;
boolean supports(ConfigAttribute var1);
boolean supports(Class<?> var1);
}AccessDecisionVoter (访问决定投票器),投票器会检查⽤户是否具备应有的角色,进而投出赞成、反对或者弃权票。接口定义如下:
public interface AccessDecisionVoter<S> {
int ACCESS_GRANTED = 1;
int ACCESS_ABSTAIN = 0;
int ACCESS_DENIED = -1;
boolean supports(ConfigAttribute var1);
boolean supports(Class<?> var1);
int vote(Authentication var1, S var2, Collection<ConfigAttribute> var3);
}需要注意的是:AccessDecisionManager 中会挨个遍历 AccessDecisionVoter,进而决定是否允许用户访问
ConfigAttribute,用来保存授权时的角色信息。接口定义如下:
public interface ConfigAttribute extends Serializable {
String getAttribute();
}- 在 Spring Security 中,用户请求⼀个资源需要的角色会被封装成一个 ConfigAttribute 对象
- 在 ConfigAttribute 中只有⼀个 getAttribute 方法,该方法返回⼀个 String 字符串,就是角色的名称。⼀般来说,角色名称都带有⼀个
ROLE_前缀,投票器 AccessDecisionVoter 所做的事情,其实就是比较用户所具各的角色和请求某个资源所需的 ConfigAtuibute 之间的关系
参考
安全框架Spring Security是什么?如何理解Spring Security的权限管理? - 掘金