Spring Security小教程 Vol 6. 初识访问控制

前言

从这期开始我们将主要对Spring Security的另一个领域Authority,通常被称为访问控制的部分进行说明。
相比较Authentication身份验证而言,客制化访问控制的可能性相对会低许多。所以我们对这部分主要是理解流程和分析设计上的一些动机为主。
管理访问控制对大多数读者来说都都不太陌生,Spring Security基于角色管理的访问控制学习起来也会较身份验证来的又有代入感。

第六期 初识访问控制

  1. 访问控制的概述
  2. 访问控制中主要的组件及实现介绍

一、关于整体结构

在之前的分享中,我们已经了解了在Spring Security中,对于访问的身份验证是通过WebFilter作为入口。然后调用AuthenticationManager暴露的验证服务接口进行验证的。
同样的,在验证身份之后,如访问受限资源,同样也会如果身份验证一样,被某个WebFilter作为入口。然后调用一个名为AccessDecisionManager的访问控制决策管理器进行验证。

AccessDecisionManager的三种主要实现类

在Spring Security中,主要关于访问控制的代码都被放在了org.springframework.security.access.vote包中,其中主要的接口分为三种:

  • AccessDecisionManager: 负责整个访问控制授权部分的投票策略和管理;
  • AccessDecisionVoter: 负责对访问控制的规则进行表决,是否授权用户访问目标资源;
  • ConfigAttribute: 用于保存相关的访问控制规则
access中主要的接口

用一句话描述他们的责任就是:AccessDecisionVoter负责对ConfigAttribute进行表决,AccessDecsionManager汇总表决,最终向框架返回最终的授权结果。

二、ConfigAttribute组件介绍

在一开始,我们先来回顾下,最早的应用中,我们是如何进行访问控制的:

    @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方法去完成。

http
        .authorizeRequests()
                .antMatchers("/user/**").access("@webSecurity.check(authentication,request)")
                ...

除了Web表达式以外,Spring Security还提供了几种进行访问控制配置的方式,其中最主要的一种便是通过注解在方法级对Controller和Service的方法进行对应的访问控制的设置。


ConfigAttribute

其中Spring Security对应方法级的注解主要又可以分为两类:
第一类 @Secured 注解 - secured-annotations
第二类 @PreAuthorize, @PreFilter, @PostAuthorize and @PostFilter - pre-post-annotations

而在Spring Security中以上两种注解默认是禁用的,我们需要通过激活配置才可以进行使用。

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
@EnableWebSecurity
public class WebSecurityConfig  extends WebSecurityConfigurerAdapter {
}

关于相关访问控制规则的详细介绍和应用,我们将在以后的专题中进行逐一说明。当前只是为将来的分析打一下基础。

三、AccessDecisionVoter组件介绍

AccessDecisionVoter可是说是整个访问控制、授权业务的核心。每一个AccessDecisionVoter都需要对它所支持的访问控制规则进行投票。投票结果只有以下三种情况:

    int ACCESS_GRANTED = 1; // 赞成
    int ACCESS_ABSTAIN = 0;  // 弃权
    int ACCESS_DENIED = -1;  // 反对
AccessDecisionVoter

AccessDecisionVoter的接口方法签名可以看出,其主要两个方法分别对应的职责一个是判断是否支持当前的访问控制规则,另一个便是对支持的访问规则进行投票。
在Spring Security提供的AccessDecisionVoter实现类主要有:

  • 基于Web表达是配置的WebExpressionVoter;
  • 基于角色名前缀'ROLE_'对角色限制判断的RoleVoter;
  • 根据当前Authentication授权形式判断的AuthenticationVoter
    而三种Voter对应的访问控制规则又有些略微的不同,在身份验证模块我们了解到基本上每一个AuthenticationProvider都需要定制化一种AuthenticationToken'。而在访问控制模块中,同样的每一个AccessDecisionVoter也可以定制化一种ConfigAttribute。例如,对于WebExpressionVoter其对应的便是之前提到的WebExpressionConfigAttribute`。

框架提供的AccessDecisionVoter一般可以满足中小应用下的访问控制的基本场景。如果我们当前开发的大型应用有复杂的访问控制模型,那么AccessDecisionVoter的客制化便是我们一定会面对的问题,在将来的专题里我们会单独针对如何客制化AccessDecisionVoter进行说明。

四、AccessDecisionManager组件介绍

AccessDecisionManager对于访问控制业务的作用与AuthenticationManager对于身份验证的业务的作用差不多。其中一个便是对暴露了唯一的访问控制验证接口。而与AuthenticationManager不同的地方是,在Spring Security中针对AuthenticationManager只提供了一种ProviderManager实现类,而AccessDecisionManager缺因为有不同的表决制度分别提供了三种实现类:

  • AffirmativeBased 一票赞同制
  • UnanimousBased 一票否决制
  • ConsensusBased 少数服从多数
AccessDecisionManager

Spring Security在默认的配置下使用的AccessDecisionManagerAffirmativeBased。如果需要变更的,则可以通过配置文件修改注入的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客制化扩展最频繁的模块。所以与别的模块介绍的流程不同,本次是先将整个访问控制模块的主要接口和组件进行基本的介绍。在后面几期中,我们将对每个组件和其应用进行展开讨论。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容