Skip to content
标签
note
字数
1079 字
阅读时间
5 分钟

介绍

Spring Security 是一个功能强大、可高度定制的 身份验证访问控制 框架,是保护基于 Spring 的应用程序的事实标准

SpringSecurity 是一个面向 Java 应用程序框架,与所有的 Spring 项目一样,它可以轻松地扩展以满足定制需求

权限管理

权限管理 = 身份认证 + 授权,简称 认证授权

整体架构:

认证流程:

认证

  • AuthenticationManager 接口,在 Spring Security 中认证是由 AuthenticationManager 来负责的,接口定义为:
java
// 当返回 Authentication 时,表示认证成功;当返回AuthenticationException 异常时,表示认证失败
public interface AuthenticationManager {
    Authentication authenticate(Authentication var1) 
    			throws AuthenticationException;
}

AuthenticationManager 主要实现类为 ProviderManager,在 ProviderManager 中管理了众多 AuthenticationProvider 实例

在⼀次完整的认证流程中,Spring Security 允许存在多个 AuthenticationProvider ,用来实现多种认证方式,这些 AuthenticationProvider 都是由 ProviderManager 进行统⼀管理

  • Authentication 接口,认证以及认证成功的信息主要是由 Authentication 的实现类进行保存的,接口定义如下:
java
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 的授权体系中,有两个关键接口:AccessDecisionManagerAccessDecisionVoter

AccessDecisionManager (访问决策管理器),用来决定此次访问是否被允许。接口定义如下:

java
public interface AccessDecisionManager {
    void decide(Authentication var1, Object var2, Collection<ConfigAttribute> var3) throws AccessDeniedException, InsufficientAuthenticationException;
    boolean supports(ConfigAttribute var1);
    boolean supports(Class<?> var1);
}

AccessDecisionVoter (访问决定投票器),投票器会检查⽤户是否具备应有的角色,进而投出赞成、反对或者弃权票。接口定义如下:

java
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,用来保存授权时的角色信息。接口定义如下:

java
public interface ConfigAttribute extends Serializable {
    String getAttribute();
}
  • 在 Spring Security 中,用户请求⼀个资源需要的角色会被封装成一个 ConfigAttribute 对象
  • 在 ConfigAttribute 中只有⼀个 getAttribute 方法,该方法返回⼀个 String 字符串,就是角色的名称。⼀般来说,角色名称都带有⼀个 ROLE_ 前缀,投票器 AccessDecisionVoter 所做的事情,其实就是比较用户所具各的角色和请求某个资源所需的 ConfigAtuibute 之间的关系

参考

安全框架Spring Security是什么?如何理解Spring Security的权限管理? - 掘金

贡献者

The avatar of contributor named as jiechen jiechen

页面历史

撰写