Spring Security 中的四種權限控制方式

Spring Security 中對於權限控制默認已經提供了不少了,可是,一個優秀的框架必須具有良好的擴展性,剛好,Spring Security 的擴展性就很是棒,咱們既可使用 Spring Security 提供的方式作受權,也能夠自定義受權邏輯。一句話,你想怎麼玩均可以!java

今天鬆哥來和你們介紹一下 Spring Security 中四種常見的權限控制方式。數據庫

  • 表達式控制 URL 路徑權限
  • 表達式控制方法權限
  • 使用過濾註解
  • 動態權限

四種方式,咱們分別來看。後端

本文是 Spring Security 系列第 30 篇,閱讀前面文章有助於更好的理解本文:跨域

  1. 挖一個大坑,Spring Security 開搞!
  2. 鬆哥手把手帶你入門 Spring Security,別再問密碼怎麼解密了
  3. 手把手教你定製 Spring Security 中的表單登陸
  4. Spring Security 作先後端分離,咱就別作頁面跳轉了!通通 JSON 交互
  5. Spring Security 中的受權操做原來這麼簡單
  6. Spring Security 如何將用戶數據存入數據庫?
  7. Spring Security+Spring Data Jpa 強強聯手,安全管理只有更簡單!
  8. Spring Boot + Spring Security 實現自動登陸功能
  9. Spring Boot 自動登陸,安全風險要怎麼控制?
  10. 在微服務項目中,Spring Security 比 Shiro 強在哪?
  11. SpringSecurity 自定義認證邏輯的兩種方式(高級玩法)
  12. Spring Security 中如何快速查看登陸用戶 IP 地址等信息?
  13. Spring Security 自動踢掉前一個登陸用戶,一個配置搞定!
  14. Spring Boot + Vue 先後端分離項目,如何踢掉已登陸用戶?
  15. Spring Security 自帶防火牆!你都不知道本身的系統有多安全!
  16. 什麼是會話固定攻擊?Spring Boot 中要如何防護會話固定攻擊?
  17. 集羣化部署,Spring Security 要如何處理 session 共享?
  18. 鬆哥手把手教你在 SpringBoot 中防護 CSRF 攻擊!so easy!
  19. 要學就學透徹!Spring Security 中 CSRF 防護源碼解析
  20. Spring Boot 中密碼加密的兩種姿式!
  21. Spring Security 要怎麼學?爲何必定要成體系的學習?
  22. Spring Security 兩種資源放行策略,千萬別用錯了!
  23. 鬆哥手把手教你入門 Spring Boot + CAS 單點登陸
  24. Spring Boot 實現單點登陸的第三種方案!
  25. Spring Boot+CAS 單點登陸,如何對接數據庫?
  26. Spring Boot+CAS 默認登陸頁面太醜了,怎麼辦?
  27. 用 Swagger 測試接口,怎麼在請求頭中攜帶 Token?
  28. Spring Boot 中三種跨域場景總結
  29. Spring Boot 中如何實現 HTTP 認證?

1.表達式控制 URL 路徑權限

首先咱們來看第一種,就是經過表達式控制 URL 路徑權限,這種方式鬆哥在以前的文章中實際上和你們講過,這裏咱們再來稍微複習一下。安全

Spring Security 支持在 URL 和方法權限控制時使用 SpEL 表達式,若是表達式返回值爲 true 則表示須要對應的權限,不然表示不須要對應的權限。提供表達式的類是 SecurityExpressionRoot:session

能夠看到,SecurityExpressionRoot 有兩個實現類,表示在應對 URL 權限控制和應對方法權限控制時,分別對 SpEL 所作的拓展,例如在基於 URL 路徑作權限控制時,增長了 hasIpAddress 選項。框架

咱們來看下 SecurityExpressionRoot 類中定義的最基本的 SpEL 有哪些:前後端分離

能夠看到,這些都是該類對應的表達式,這些表達式我來給你們稍微解釋下:函數

表達式 備註
hasRole 用戶具有某個角色便可訪問資源
hasAnyRole 用戶具有多個角色中的任意一個便可訪問資源
hasAuthority 相似於 hasRole
hasAnyAuthority 相似於 hasAnyRole
permitAll 通通容許訪問
denyAll 通通拒絕訪問
isAnonymous 判斷是否匿名用戶
isAuthenticated 判斷是否定證成功
isRememberMe 判斷是否經過記住我登陸的
isFullyAuthenticated 判斷是否用戶名/密碼登陸的
principle 當前用戶
authentication 從 SecurityContext 中提取出來的用戶對象

這是最基本的,在它的繼承類中,還有作一些拓展,我這個我就不重複介紹了。微服務

若是是經過 URL 進行權限控制,那麼咱們只須要按照以下方式配置便可:

protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/admin/**").hasRole("admin")
            .antMatchers("/user/**").hasAnyRole("admin", "user")
            .anyRequest().authenticated()
            .and()
            ...
}

這裏表示訪問 /admin/** 格式的路徑須要 admin 角色,訪問 /user/** 格式的路徑須要 admin 或者 user 角色。

2.表達式控制方法權限

固然,咱們也能夠經過在方法上添加註解來控制權限。

在方法上添加註解控制權限,須要咱們首先開啓註解的使用,在 Spring Security 配置類上添加以下內容:

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

這個配置開啓了三個註解,分別是:

  • @PreAuthorize:方法執行前進行權限檢查
  • @PostAuthorize:方法執行後進行權限檢查
  • @Secured:相似於 @PreAuthorize

這三個結合 SpEL 以後,用法很是靈活,這裏和你們稍微分享幾個 Demo。

@Service
public class HelloService {
    @PreAuthorize("principal.username.equals('javaboy')")
    public String hello() {
        return "hello";
    }

    @PreAuthorize("hasRole('admin')")
    public String admin() {
        return "admin";
    }

    @Secured({"ROLE_user"})
    public String user() {
        return "user";
    }

    @PreAuthorize("#age>98")
    public String getAge(Integer age) {
        return String.valueOf(age);
    }
}
  1. 第一個 hello 方法,註解的約束是,只有當前登陸用戶名爲 javaboy 的用戶才能夠訪問該方法。
  2. 第二個 admin 方法,表示訪問該方法的用戶必須具有 admin 角色。
  3. 第三個 user 方法,表示方法該方法的用戶必須具有 user 角色,可是注意 user 角色須要加上 ROLE_ 前綴。
  4. 第四個 getAge 方法,表示訪問該方法的 age 參數必須大於 98,不然請求不予經過。

能夠看到,這裏的表達式仍是很是豐富,若是想引用方法的參數,前面加上一個 # 便可,既能夠引用基本類型的參數,也能夠引用對象參數。

缺省對象除了 principal ,還有 authentication(參考第一小節)。

3.使用過濾註解

Spring Security 中還有兩個過濾函數 @PreFilter 和 @PostFilter,能夠根據給出的條件,自動移除集合中的元素。

@PostFilter("filterObject.lastIndexOf('2')!=-1")
public List<String> getAllUser() {
    List<String> users = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        users.add("javaboy:" + i);
    }
    return users;
}
@PreFilter(filterTarget = "ages",value = "filterObject%2==0")
public void getAllAge(List<Integer> ages,List<String> users) {
    System.out.println("ages = " + ages);
    System.out.println("users = " + users);
}
  • 在 getAllUser 方法中,對集合進行過濾,只返回後綴爲 2 的元素,filterObject 表示要過濾的元素對象。
  • 在 getAllAge 方法中,因爲有兩個集合,所以使用 filterTarget 指定過濾對象。

4.動態權限

動態權限主要經過重寫攔截器和決策器來實現,這個我在 vhr 的文檔中有過詳細介紹,你們在公衆號【江南一點雨】後臺回覆 888 能夠獲取文檔,我就再也不贅述了。

5.小結

好啦,今天就喝小夥伴們稍微聊了一下 Spring Security 中的受權問題,固然這裏還有不少細節,後面鬆哥再和你們一一細聊。

若是小夥伴們以爲有收穫,記得點個在看鼓勵下鬆哥哦~

相關文章
相關標籤/搜索