Spring Security小教程 Vol 6. 初識訪問控制

前言

從這期開始我們將主要對Spring Security的另一個領(lǐng)域Authority,通常被稱為訪問控制的部分進行說明。
相比較Authentication身份驗證而言,客制化訪問控制的可能性相對會低許多。所以我們對這部分主要是理解流程和分析設(shè)計上的一些動機為主。
管理訪問控制對大多數(shù)讀者來說都都不太陌生,Spring Security基于角色管理的訪問控制學(xué)習(xí)起來也會較身份驗證來的又有代入感。

第六期 初識訪問控制

  1. 訪問控制的概述
  2. 訪問控制中主要的組件及實現(xiàn)介紹

一、關(guān)于整體結(jié)構(gòu)

在之前的分享中,我們已經(jīng)了解了在Spring Security中,對于訪問的身份驗證是通過WebFilter作為入口。然后調(diào)用AuthenticationManager暴露的驗證服務(wù)接口進行驗證的。
同樣的,在驗證身份之后,如訪問受限資源,同樣也會如果身份驗證一樣,被某個WebFilter作為入口。然后調(diào)用一個名為AccessDecisionManager的訪問控制決策管理器進行驗證。

AccessDecisionManager的三種主要實現(xiàn)類

在Spring Security中,主要關(guān)于訪問控制的代碼都被放在了org.springframework.security.access.vote包中,其中主要的接口分為三種:

  • AccessDecisionManager: 負責(zé)整個訪問控制授權(quán)部分的投票策略和管理;
  • AccessDecisionVoter: 負責(zé)對訪問控制的規(guī)則進行表決,是否授權(quán)用戶訪問目標(biāo)資源;
  • ConfigAttribute: 用于保存相關(guān)的訪問控制規(guī)則
access中主要的接口

用一句話描述他們的責(zé)任就是:AccessDecisionVoter負責(zé)對ConfigAttribute進行表決,AccessDecsionManager匯總表決,最終向框架返回最終的授權(quán)結(jié)果。

二、ConfigAttribute組件介紹

在一開始,我們先來回顧下,最早的應(yīng)用中,我們是如何進行訪問控制的:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/user").hasRole("USER")
                .antMatchers("/user").denyAll()
                .and()
                .formLogin();
    }

我們通過在configure方法中編寫路徑模式和相應(yīng)的限定規(guī)則來配置整個應(yīng)用的訪問控制,基于Web表達式的訪問控制規(guī)則,除了支持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的方法進行對應(yīng)的訪問控制的設(shè)置。


ConfigAttribute

其中Spring Security對應(yīng)方法級的注解主要又可以分為兩類:
第一類 @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 {
}

關(guān)于相關(guān)訪問控制規(guī)則的詳細介紹和應(yīng)用,我們將在以后的專題中進行逐一說明。當(dāng)前只是為將來的分析打一下基礎(chǔ)。

三、AccessDecisionVoter組件介紹

AccessDecisionVoter可是說是整個訪問控制、授權(quán)業(yè)務(wù)的核心。每一個AccessDecisionVoter都需要對它所支持的訪問控制規(guī)則進行投票。投票結(jié)果只有以下三種情況:

    int ACCESS_GRANTED = 1; // 贊成
    int ACCESS_ABSTAIN = 0;  // 棄權(quán)
    int ACCESS_DENIED = -1;  // 反對
AccessDecisionVoter

AccessDecisionVoter的接口方法簽名可以看出,其主要兩個方法分別對應(yīng)的職責(zé)一個是判斷是否支持當(dāng)前的訪問控制規(guī)則,另一個便是對支持的訪問規(guī)則進行投票。
在Spring Security提供的AccessDecisionVoter實現(xiàn)類主要有:

  • 基于Web表達是配置的WebExpressionVoter;
  • 基于角色名前綴'ROLE_'對角色限制判斷的RoleVoter;
  • 根據(jù)當(dāng)前Authentication授權(quán)形式判斷的AuthenticationVoter
    而三種Voter對應(yīng)的訪問控制規(guī)則又有些略微的不同,在身份驗證模塊我們了解到基本上每一個AuthenticationProvider都需要定制化一種AuthenticationToken'。而在訪問控制模塊中,同樣的每一個AccessDecisionVoter也可以定制化一種ConfigAttribute。例如,對于WebExpressionVoter其對應(yīng)的便是之前提到的WebExpressionConfigAttribute`。

框架提供的AccessDecisionVoter一般可以滿足中小應(yīng)用下的訪問控制的基本場景。如果我們當(dāng)前開發(fā)的大型應(yīng)用有復(fù)雜的訪問控制模型,那么AccessDecisionVoter的客制化便是我們一定會面對的問題,在將來的專題里我們會單獨針對如何客制化AccessDecisionVoter進行說明。

四、AccessDecisionManager組件介紹

AccessDecisionManager對于訪問控制業(yè)務(wù)的作用與AuthenticationManager對于身份驗證的業(yè)務(wù)的作用差不多。其中一個便是對暴露了唯一的訪問控制驗證接口。而與AuthenticationManager不同的地方是,在Spring Security中針對AuthenticationManager只提供了一種ProviderManager實現(xiàn)類,而AccessDecisionManager缺因為有不同的表決制度分別提供了三種實現(xiàn)類:

  • AffirmativeBased 一票贊同制
  • UnanimousBased 一票否決制
  • ConsensusBased 少數(shù)服從多數(shù)
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而言,框架提供的的三種表決制度在絕大多數(shù)情況都已經(jīng)足夠強大。我們對于其的了解便只需要集中在如何配置和管理使用的AccessDecisionVoter便可。

結(jié)尾

訪問控制相關(guān)通常是我們使用Spring Security客制化擴展最頻繁的模塊。所以與別的模塊介紹的流程不同,本次是先將整個訪問控制模塊的主要接口和組件進行基本的介紹。在后面幾期中,我們將對每個組件和其應(yīng)用進行展開討論。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容