从这期开始咱们将主要对Spring Security的另外一个领域Authority,一般被称为访问控制的部分进行说明。 相比较Authentication身份验证而言,客制化访问控制的可能性相对会低许多。因此咱们对这部分主要是理解流程和分析设计上的一些动机为主。 管理访问控制对大多数读者来讲都都不太陌生,Spring Security基于角色管理的访问控制学习起来也会较身份验证来的又有代入感。java
在以前的分享中,咱们已经了解了在Spring Security中,对于访问的身份验证是经过WebFilter做为入口。而后调用AuthenticationManager
暴露的验证服务接口进行验证的。 一样的,在验证身份以后,如访问受限资源,一样也会若是身份验证同样,被某个WebFilter做为入口。而后调用一个名为AccessDecisionManager
的访问控制决策管理器进行验证。 web
在Spring Security中,主要关于访问控制的代码都被放在了org.springframework.security.access.vote
包中,其中主要的接口分为三种:spring
AccessDecisionManager
: 负责整个访问控制受权部分的投票策略和管理;AccessDecisionVoter
: 负责对访问控制的规则进行表决,是否受权用户访问目标资源;ConfigAttribute
: 用于保存相关的访问控制规则用一句话描述他们的责任就是:AccessDecisionVoter
负责对ConfigAttribute
进行表决,AccessDecsionManager
汇总表决,最终向框架返回最终的受权结果。bash
在一开始,咱们先来回顾下,最先的应用中,咱们是如何进行访问控制的:框架
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/user").hasRole("USER")
.antMatchers("/user").denyAll()
.and()
.formLogin();
}
复制代码
咱们经过在configure方法中编写路径模式和相应的限定规则来配置整个应用的访问控制,基于Web表达式的访问控制规则,除了支持Spring Security中默认提供的一些限制方法之外,也能够额经过.antMatchers("/user").access("hasRole('USER') or hasRole('ADMIN')")
的access方法加上表达式的形式进行扩展。表达式更是能够将表达判断委托给一个Java Class去完成。 好比下方示例代码就是讲表达式的判断委托给了名为webSecurity的Bean中的check方法去完成。ide
http
.authorizeRequests()
.antMatchers("/user/**").access("@webSecurity.check(authentication,request)")
...
复制代码
除了Web表达式之外,Spring Security还提供了几种进行访问控制配置的方式,其中最主要的一种即是经过注解在方法级对Controller和Service的方法进行对应的访问控制的设置。 post
其中Spring Security对应方法级的注解主要又能够分为两类:学习
@Secured
注解 - secured-annotations@PreAuthorize, @PreFilter, @PostAuthorize and @PostFilter
- pre-post-annotations而在Spring Security中以上两种注解默认是禁用的,咱们须要经过激活配置才能够进行使用。ui
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
}
复制代码
关于相关访问控制规则的详细介绍和应用,咱们将在之后的专题中进行逐一说明。当前只是为未来的分析打一下基础。spa
AccessDecisionVoter
但是说是整个访问控制、受权业务的核心。每个AccessDecisionVoter
都须要对它所支持的访问控制规则进行投票。投票结果只有如下三种状况:
int ACCESS_GRANTED = 1; // 同意
int ACCESS_ABSTAIN = 0; // 弃权
int ACCESS_DENIED = -1; // 反对
复制代码
从AccessDecisionVoter
的接口方法签名能够看出,其主要两个方法分别对应的职责一个是判断是否支持当前的访问控制规则,另外一个即是对支持的访问规则进行投票。 在Spring Security提供的AccessDecisionVoter
实现类主要有:
WebExpressionVoter
;RoleVoter
;AuthenticationVoter
。 而三种Voter对应的访问控制规则又有些略微的不一样,在身份验证模块咱们了解到基本上每个AuthenticationProvider
都须要定制化一种AuthenticationToken'。而在访问控制模块中,一样的每个
AccessDecisionVoter也能够定制化一种
ConfigAttribute。例如,对于
WebExpressionVoter其对应的即是以前提到的
WebExpressionConfigAttribute`。框架提供的AccessDecisionVoter通常能够知足中小应用下的访问控制的基本场景。若是咱们当前开发的大型应用有复杂的访问控制模型,那么
AccessDecisionVoter
的客制化即是咱们必定会面对的问题,在未来的专题里咱们会单独针对如何客制化AccessDecisionVoter
进行说明。
AccessDecisionManager
对于访问控制业务的做用与AuthenticationManager
对于身份验证的业务的做用差很少。其中一个即是对暴露了惟一的访问控制验证接口。而与AuthenticationManager
不一样的地方是,在Spring Security中针对AuthenticationManager
只提供了一种ProviderManager
实现类,而AccessDecisionManager
缺由于有不一样的表决制度分别提供了三种实现类:
AffirmativeBased
一票赞同制UnanimousBased
一票否决制ConsensusBased
少数服从多数Spring Security在默认的配置下使用的AccessDecisionManager
是AffirmativeBased
。若是须要变动的,则能够经过配置文件修改注入的Bean便可,好比下面的Java Config形式。
@Bean
public AccessDecisionManager accessDecisionManager() {
List<AccessDecisionVoter<? extends Object>> decisionVoters
= Arrays.asList(
new WebExpressionVoter(),
new RoleVoter(),
new AuthenticatedVoter()
);
return new UnanimousBased(decisionVoters);
}
复制代码
对于
AccessDecisionManager
而言,框架提供的的三种表决制度在绝大多数状况都已经足够强大。咱们对于其的了解便只须要集中在如何配置和管理使用的AccessDecisionVoter
即可。
访问控制相关一般是咱们使用Spring Security客制化扩展最频繁的模块。因此与别的模块介绍的流程不一样,本次是先将整个访问控制模块的主要接口和组件进行基本的介绍。在后面几期中,咱们将对每一个组件和其应用进行展开讨论。