欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring?Security實現基于RBAC的權限表達式動態(tài)訪問控制的操作方法

 更新時間:2022年04月20日 08:40:03   作者:碼農小胖哥  
這篇文章主要介紹了Spring?Security實現基于RBAC的權限表達式動態(tài)訪問控制,資源權限表達式動態(tài)權限控制在Spring Security也是可以實現的,首先開啟方法級別的注解安全控制,本文結合實例代碼給大家介紹的非常詳細,需要的朋友可以參考下

昨天有個粉絲加了我,問我如何實現類似shiro的資源權限表達式的訪問控制。我以前有一個小框架用的就是shiro,權限控制就用了資源權限表達式,所以這個東西對我不陌生,但是在Spring Security中我并沒有使用過它,不過我認為Spring Security可以實現這一點。是的,我找到了實現它的方法。

資源權限表達式

說了這么多,我覺得應該解釋一下什么叫資源權限表達式。權限控制的核心就是清晰地表達出特定資源的某種操作,一個格式良好好的權限聲明可以清晰表達出用戶對該資源擁有的操作權限。

通常一個資源在系統(tǒng)中的標識是唯一的,比如User用來標識用戶,ORDER標識訂單。不管什么資源大都可以歸納出以下這幾種操作

在 shiro權限聲明通常對上面的這種資源操作關系用冒號分隔的方式進行表示。例如讀取用戶信息的操作表示為USER:READ,甚至還可以更加細一些,用USER:READ:123表示讀取ID為123的用戶權限。

資源操作定義好了,再把它和角色關聯起來不就是基于RBAC的權限資源控制了嗎?就像下面這樣:

這樣資源和角色的關系可以進行CRUD操作進行動態(tài)綁定。

Spring Security中的實現

資源權限表達式動態(tài)權限控制在Spring Security也是可以實現的。首先開啟方法級別的注解安全控制。

/**
 * 開啟方法安全注解
 *
 * @author felord.cn
 */
@EnableGlobalMethodSecurity(prePostEnabled = true,
        securedEnabled = true,
        jsr250Enabled = true)
public class MethodSecurityConfig {
    
}

MethodSecurityExpressionHandler

MethodSecurityExpressionHandler 提供了一個對方法進行安全訪問的門面擴展。它的實現類DefaultMethodSecurityExpressionHandler更是提供了針對方法的一系列擴展接口,這里我總結了一下:

這里的PermissionEvaluator正好可以滿足需要。

PermissionEvaluator

PermissionEvaluator 接口抽象了對一個用戶是否有權限訪問一個特定的領域對象的評估過程。

public interface PermissionEvaluator extends AopInfrastructureBean {
	boolean hasPermission(Authentication authentication, 
                          Object targetDomainObject, Object permission);
                          Serializable targetId, String targetType, Object permission);
}

這兩個方法僅僅參數列表不同,這些參數的含義為:

  • authentication 當前用戶的認證信息,持有當前用戶的角色權限。
  • targetDomainObject 用戶想要訪問的目標領域對象,例如上面的USER。
  • permission 這個當前方法設定的目標領域對象的權限,例如上面的READ。
  • targetId 這種是對上面targetDomainObject 的具體化,比如ID為123USER,我覺得還可以搞成租戶什么的。
  • targetType 是為了配合targetId 。

第一個方法是用來實現USER:READ的;第二個方法是用來實現USER:READ:123的。

思路以及實現

targetDomainObject:permission不就是USER:READ的抽象嗎?只要找出USER:READ對應的角色集合,和當前用戶持有的角色進行比對,它們存在交集就證明用戶有權限訪問。借著這個思路胖哥實現了一個PermissionEvaluator:

/**
 * 資源權限評估
 * 
 * @author felord.cn
 */
public class ResourcePermissionEvaluator implements PermissionEvaluator {
    private final BiFunction<String, String, Collection<? extends GrantedAuthority>> permissionFunction;

    public ResourcePermissionEvaluator(BiFunction<String, String, Collection<? extends GrantedAuthority>> permissionFunction) {
        this.permissionFunction = permissionFunction;
    }
    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
        //查詢方法標注對應的角色
        Collection<? extends GrantedAuthority> resourceAuthorities = permissionFunction.apply((String) targetDomainObject, (String) permission);
        // 用戶對應的角色
        Collection<? extends GrantedAuthority> userAuthorities = authentication.getAuthorities();
         // 對比 true 就能訪問  false 就不能訪問
        return userAuthorities.stream().anyMatch(resourceAuthorities::contains);
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        //todo
        System.out.println("targetId = " + targetId);
        return true;
}

第二個方法沒有實現,因為兩個差不多,第二個你可以想想具體的使用場景。

配置和使用

PermissionEvaluator 需要注入到Spring IoC,并且Spring IoC只能有一個該類型的Bean:

@Bean
    PermissionEvaluator resourcePermissionEvaluator() {
        return new ResourcePermissionEvaluator((targetDomainObject, permission) -> {
            //TODO 這里形式其實可以不固定
            String key = targetDomainObject + ":" + permission;
            //TODO  查詢 key 和  authority 的關聯關系
            //  模擬 permission 關聯角色   根據key 去查 grantedAuthorities
            Set<SimpleGrantedAuthority> grantedAuthorities = new HashSet<>();
            grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
            return "USER:READ".equals(key) ? grantedAuthorities : new HashSet<>();
        });
    }

接下來寫個接口,用@PreAuthorize注解標記,然后直接用hasPermission('USER','READ')來靜態(tài)綁定該接口的訪問權限表達式:

 @GetMapping("/postfilter")
    @PreAuthorize("hasPermission('USER','READ')")
    public Collection<String> postfilter(){
        List<String> list = new ArrayList<>();
        list.add("felord.cn");
        list.add("碼農小胖哥");
        list.add("請關注一下");
        return list;
    }

然后定義一個用戶:

  @Bean
    UserDetailsService users() {
        UserDetails user = User.builder()
                .username("felord")
                .password("123456")
      .passwordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder()::encode)
                .roles("USER")
                .authorities("ROLE_ADMIN","ROLE_USER")
                .build();
        return new InMemoryUserDetailsManager(user);
    }

接下來肯定是正常能夠訪問接口的。當你改變了@PreAuthorize中表達式的值或者移除了用戶的ROLE_ADMIN權限,再或者USER:READ關聯到了其它角色等等,都會返回403。

留給你去測試的

你可以看看注解改成這樣會是什么效果:

@PreAuthorize("hasPermission('1234','USER','READ')")

還有這個:

@PreAuthorize("hasPermission('USER','READ') or hasRole('ADMIN')")

或者讓targetId動態(tài)化:

 @PreAuthorize("hasPermission(#id,'USER','READ')")
    public Collection<String> postfilter(String id){
        
    }

到此這篇關于Spring Security實現基于RBAC的權限表達式動態(tài)訪問控制的文章就介紹到這了,更多相關Spring Security實現RBAC權限表達式內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java面向對象程序設計:類的定義,靜態(tài)變量,成員變量,構造函數,封裝與私有,this概念與用法詳解

    Java面向對象程序設計:類的定義,靜態(tài)變量,成員變量,構造函數,封裝與私有,this概念與用法詳解

    這篇文章主要介紹了Java面向對象類的定義,靜態(tài)變量,成員變量,構造函數,封裝與私有,this概念與用法,較為詳細的分析了Java類的定義,靜態(tài)變量,成員變量,構造函數,封裝,私有等相關原理、用法及操作注意事項,需要的朋友可以參考下
    2020-04-04
  • 詳解SpringMVC加載配置Properties文件的幾種方式

    詳解SpringMVC加載配置Properties文件的幾種方式

    這篇文章主要介紹了詳解SpringMVC加載配置Properties文件的幾種方式,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-02-02
  • Java工程如何打印程序日志過程解析

    Java工程如何打印程序日志過程解析

    這篇文章主要介紹了Java工程如何打印程序日志過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-10-10
  • Java語言通過三種方法實現隊列的示例代碼

    Java語言通過三種方法實現隊列的示例代碼

    這篇文章主要介紹了Java語言通過三種方法來實現隊列的實例代碼,數組模擬隊列,通過對定義的了解,發(fā)現隊列很像我們的數組,下面我們通過實踐給大家詳細介紹,需要的朋友可以參考下
    2022-02-02
  • Java如何讀寫Properties配置文件(Properties類)

    Java如何讀寫Properties配置文件(Properties類)

    這篇文章主要介紹了Java如何讀寫Properties配置文件(Properties類),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • SpringBoot實現自定義Starter的步驟詳解

    SpringBoot實現自定義Starter的步驟詳解

    在SpringBoot中,Starter是一種特殊的依賴,它可以幫助我們快速地集成一些常用的功能,例如數據庫連接、消息隊列、Web框架等。在本文中,我們將介紹如何使用Spring Boot實現自定義Starter,需要的朋友可以參考下
    2023-06-06
  • 詳解springcloud組件consul服務治理

    詳解springcloud組件consul服務治理

    Consul是一款由HashiCorp公司開源的,用于服務治理的軟件,Spring Cloud Consul對其進行了封裝,這篇文章主要介紹了springcloud組件consul服務治理,需要的朋友可以參考下
    2022-08-08
  • Java中Calendar日歷類型常見方法詳解

    Java中Calendar日歷類型常見方法詳解

    Calendar是Java中常用的時間處理工具之一,它提供了很多日歷類型常見方法,下面是一些常用的方法及對應的代碼和運行結果,感興趣的朋友一起看看吧
    2023-11-11
  • Java Lock鎖多線程中實現流水線任務

    Java Lock鎖多線程中實現流水線任務

    這篇文章主要介紹了Java Lock鎖多線程中實現流水線任務,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-05-05
  • java 線程方法join簡單用法實例總結

    java 線程方法join簡單用法實例總結

    這篇文章主要介紹了java 線程方法join簡單用法,結合實例形式總結分析了Java線程join方法的功能、原理及使用技巧,需要的朋友可以參考下
    2019-11-11

最新評論