授权架构重点在于从 Authentication 中获得该认证所具有的权限 GrantedAuthority,以及对请求或路径设置访问所需权限。
GrantedAuthority
在之前的Spring Security:认证架构中,我们已经介绍了在 Authentication 中存储 GrantedAuthority 的方式,Authentication 拥有一个 GrantedAuthority 的集合,这代表了这个认证所具有的权限。
AccessDecisionManager(一个用来校验认证 Authentication 是否具有所需权限的接口)将从 Authentication 中获得 GrantedAuthority ,并调用 GrantedAuthority 接口唯一的一个方法 String getAuthority() 来获得所拥有权限的一个精确的 String 表示。
默认情况下,基于角色的授权规则以 ROLE_ 作为前缀。这意味着,如果有一个授权规则要求 security context 的角色是 "USER",Spring Security 将默认寻找调用 getAuthority() 返回 "ROLE_USER" 的 GrantedAuthority。
配置GrantedAuthorityDefaults Bean可以更改前缀:
@Bean
static GrantedAuthorityDefaults grantedAuthorityDefaults() {return new GrantedAuthorityDefaults("MYPREFIX_");
}
AuthorizationManager
AuthorizationManager 是做出最终的访问控制决定的接口,被各类授权组件所调用,包含两个方法:
AuthorizationDecision check(Supplier<Authentication> authentication, Object secureObject);default AuthorizationDecision verify(Supplier<Authentication> authentication, Object secureObject)throws AccessDeniedException {// ...
}
AuthorizationManager 的 check 方法被传递它所需要的所有相关信息,以便做出授权决定。
secureObject 中包含需要的任何客户参数,然后 AuthorizationManager 中进行验证。如果通过,返回“positive”的AuthorizationDecision;如果不通过,返回“negative”的AuthorizationDecision;如果不作出决定,则返回空的 AuthorizationDecision。
verify 方法调用 check,然后在出现 "negative" 的 AuthorizationDecision 决定时抛出一个 AccessDeniedException。
Spring Security 提供了一个代理类的 AuthorizationManager(RequestMatcherDelegatingAuthorizationManager),可以与别的 AuthorizationManager 协作。
常用的实现:
- AuthorityAuthorizationManager:在当前 Authentication 中寻找一组给定的授权。如果包含任一配置的授权,返回 positive,否则返回 negative。
- AuthenticatedAuthorizationManager:用来区分匿名、完全认证和记住我认证的用户。许多网站在Remember-me认证下允许某些有限的访问,但要求用户通过登录来确认他们的身份以获得完整的访问。
- 其他请自行了解。
基本流程
(仅为基于HTTP请求授权的基本流程)
注意:默认情况下,AuthorizationFilter 是 Spring Security filter chain 中的最后一个,这说明 Spring Security 的 authentication filter、漏洞保护 和其他 filter 集成都不需要授权。如果你在 AuthorizationFilter 之前添加自己的 filter,它们也将不需要授权;否则,它们将需要授权。(Spring MVC的 DispatcherServlet 位于 AuthorizationFilter 之后,所以都是需要授权的。)
- 首先,AuthorizationFilter 构造一个 Supplier,从 SecurityContextHolder 中检索一个 Authentication。
- 将 Supplier 和 HttpServletRequest 传递给 AuthorizationManager。AuthorizationManager 将请求与 authorizeHttpRequests 中的模式相匹配,并运行相应的规则。
- 如果没有权限,会发布一个 AuthorizationDeniedEvent,并抛出一个 AccessDeniedException。在这种情况下,ExceptionTranslationFilter 会处理 AccessDeniedException。
- 如果拥有权限,会发布一个 AuthorizationGrantedEvent,进入后续的过滤器链。