1. 程式人生 > >使用Spring安全表示式控制系統功能訪問許可權

使用Spring安全表示式控制系統功能訪問許可權

一、SPEL表示式許可權控制

spring security 3.0開始已經可以使用spring Expression表示式來控制授權,允許在表示式中使用複雜的布林邏輯來控制訪問的許可權。Spring Security可用表示式物件的基類是SecurityExpressionRoot。

表示式函式 描述
hasRole([role]) 使用者擁有指定的角色時返回true (Spring security預設會帶有ROLE_字首),去除字首參考Remove the ROLE_
hasAnyRole([role1,role2]) 使用者擁有任意一個指定的角色時返回true
hasAuthority([authority])
擁有某資源的訪問許可權時返回true
hasAnyAuthority([auth1,auth2]) 擁有某些資源其中部分資源的訪問許可權時返回true
permitAll 永遠返回true
denyAll 永遠返回false
anonymous 當前使用者是anonymous時返回true
rememberMe 當前使用者是rememberMe使用者返回true
authentication 當前登入使用者的authentication物件
fullAuthenticated 當前使用者既不是anonymous也不是rememberMe使用者時返回true
hasIpAddress('192.168.1.0/24'))
請求傳送的IP匹配時返回true

部分朋友可能會對Authority和Role有些混淆。Authority作為資源訪問許可權可大可小,可以是某按鈕的訪問許可權(如資源ID:biz1),也可以是某類使用者角色的訪問許可權(如資源ID:ADMIN)。當Authority作為角色資源許可權時,hasAuthority('ROLE_ADMIN')與hasRole('ADMIN')是一樣的效果。

二、SPEL在全域性配置中的使用

我們可以通過繼承WebSecurityConfigurerAdapter,實現相關的配置方法,進行全域性的安全配置(之前的章節已經講過) 。下面就為大家介紹一些如何在全域性配置中使用SPEL表示式。

2.1.URL安全表示式

config.antMatchers("/system/*").access("hasAuthority('ADMIN') or hasAuthority('USER')")
      .anyRequest().authenticated();

這裡我們定義了應用/person/*URL的範圍,只有擁有ADMIN或者USER許可權的使用者才能訪問這些person資源。

2.2.安全表示式中引用bean

這種方式,比較適合有複雜許可權驗證邏輯的情況,當Spring Security提供的預設表示式方法無法滿足我們的需求的時候。首先我們定義一個許可權驗證的RbacService。

@Component("rbacService")
@Slf4j
public class RbacService {
    //返回true表示驗證通過
    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        //驗證邏輯程式碼
        return true;
    }
    public boolean checkUserId(Authentication authentication, int id) {
        //驗證邏輯程式碼
        return true;
    }
}

對於"/person/{id}"對應的資源的訪問,呼叫rbacService的bean的方法checkUserId進行許可權驗證,傳遞引數為authentication物件和person的id。該id為PathVariable,以#開頭表示。

config.antMatchers("/person/{id}").access("@rbacService.checkUserId(authentication,#id)")
      .anyRequest().access("@rbacService.hasPermission(request,authentication)");

三、 Method表示式安全控制

如果我們想實現方法級別的安全配置,Spring Security提供了四種註解,分別是@PreAuthorize , @PreFilter , @PostAuthorize 和 @PostFilter

3.1.開啟方法級別註解的配置

在Spring安全配置程式碼中,加上EnableGlobalMethodSecurity註解,開啟方法級別安全配置功能。

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

3.2 使用PreAuthorize註解

@PreAuthorize 註解適合進入方法前的許可權驗證。只有擁有ADMIN角色才能訪問findAll方法。

@PreAuthorize("hasRole('ADMIN')")
List<Person> findAll();

3.3 使用PostAuthorize註解

@PostAuthorize 在方法執行後再進行許可權驗證,適合根據返回值結果進行許可權驗證。Spring EL 提供返回物件能夠在表示式語言中獲取返回的物件returnObject。下文程式碼只有返回值的name等於authentication物件的name才能正確返回,否則丟擲異常。

@PostAuthorize("returnObject.name == authentication.name")
Person findOne(Integer id);

3.4 使用PreFilter註解

PreFilter 針對引數進行過濾,下文程式碼表示針對ids引數進行過濾,只有id為偶數才能訪問delete方法。

//當有多個物件是使用filterTarget進行標註
@PreFilter(filterTarget="ids", value="filterObject%2==0")
public void delete(List<Integer> ids, List<String> usernames) {

3.5 使用PostFilter 註解

PostFilter 針對返回結果進行過濾,特別適用於集合類返回值,過濾集合中不符合表示式的物件。

@PostFilter("filterObject.name == authentication.name")
List<Person> findAll();

期待您的關注

  • 博主最近新寫了一本書:《手摸手教您學習SpringBoot系列-16章97節》
  • 本文轉載註明出處(必須帶連線,不能只轉文字):字母哥部落格。