Spring Security
谈到应用安全框架就离不开两个核心功能:认证(Authentication)、授权(Authorization)。
- 认证
解决 “你是谁?” 的问题。常用的认证方式就是用户登录验证。 - 授权
解决 “你能干什么?” 的问题。
上篇文章已经介绍了认证功能,本文续接上文,继续介绍授权功能。
授权(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
;
也有方法维度鉴权的实现: RoleVoter
、AuthenticatedVoter
(用于处理 @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