Spring Security


谈到应用安全框架就离不开两个核心功能:认证(Authentication)、授权(Authorization)。

  1. 认证
    解决 “你是谁?” 的问题。常用的认证方式就是用户登录验证。
  2. 授权
    解决 “你能干什么?” 的问题。

上篇文章已经介绍了认证功能,本文续接上文,继续介绍授权功能。

授权(Authorization)

通常"授权"也被称为"权限控制"(Access Control),为了便于理解,经常又称之为鉴权。

鉴权需要在真正逻辑之前处理,整个流程就涉及:权限信息的获取、判断是否有权限、权限不足的处理、匿名访问的处理。
注意,匿名访问不同于权限不足,匿名访问指的是没有经过认证就访问接口,权限不足指的是用户通过认证了,但是没有访问该接口的权限。

同样的,下面介绍 Spring Security 对上述的功能点是如何设计的。

鉴权拦截器

Spring Security设计了 FilterSecurityInterceptor 过滤器来执行鉴权的逻辑。

权限信息查询

Spring Security设计了 GrantedAuthority 接口来定义权限信息,其接口定义如下:

public interface GrantedAuthority extends Serializable {
    String getAuthority();
}

GrantedAuthority只是用来定义权限信息,那它是从哪里获取的呢?
其实在上文中我们已经提到 UserDetailsService,其loadUserByUsername方法返回值为 UserDetails,而其中定义的 Collection<? extends GrantedAuthority> getAuthorities(); 正是返回权限信息列表。
可见在获取用户信息时,需要将权限信息一并获取,并组装到 UserDetails 中。

判断是否有权限

Spring Security设计了 AccessDecisionVoter 接口用于判断是否有权限(鉴权),其接口定义如下:

public interface AccessDecisionVoter<S> {
    int vote(Authentication authentication, S object, Collection<ConfigAttribute> attributes);
}

vote 方法定义了鉴权逻辑,当鉴权通过时返回 1,鉴权不通过时返回 -1,不参与判断(弃权)则返回0。

内置多个实现,有接口维度鉴权的实现:WebExpressionVoter
也有方法维度鉴权的实现: RoleVoterAuthenticatedVoter(用于处理 @Secured 权限注解)、PreInvocationAuthorizationAdviceVoter(用于处理 @PreAuthorize 权限注解)等等

权限不足的处理

Spring Security设计了 AccessDeniedHandler 接口来定义权限不足的处理逻辑,其接口定义如下:

public interface AccessDeniedHandler {
    void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException;
}

匿名访问的处理

Spring Security设计了 AuthenticationEntryPoint 接口来定义匿名访问的处理逻辑,其接口定义如下:

public interface AuthenticationEntryPoint {
    void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException;
}

end