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

SpringCloud?微服務數據權限控制的實現

 更新時間:2021年11月24日 17:14:25   作者:barry的異想世界  
這篇文章主要介紹的是權限控制的數據權限層面,意思是控制可訪問數據資源的數量,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧

舉個例子:

有一批業(yè)務員跟進全國的銷售訂單。他們被按城市進行劃分,一個業(yè)務員跟進3個城市的訂單,為了保護公司的業(yè)務數據不能被所有人都掌握,故每個業(yè)務員只能看到自己負責城市的訂單數據。所以從系統(tǒng)來講每個業(yè)務員都有訪問銷售訂單的功能,然后再需要配置每個業(yè)務員負責的城市,以此對訂單數據進行篩選。

要實現此功能有很多方法,如果系統(tǒng)中多個地方都需要類似的需求,那我們就可以將其提出來做成一個通用的功能。這里我介紹一個相對簡單的解決方案,以供參考。

一、 整體架構

數據權限為作一個注解的形式掛在每一個需要數據權限控制的Controller上,由于和具體的程序邏輯有關故有一定的入侵性,且需要數據庫配合使用。

二、 實現流程

1.瀏覽器傳帶查詢權限范圍參數訪問Controller,如cities

POST http://127.0.0.1:8000/order/query
accept: */*
Content-Type: application/json
token: 1e2b2298-8274-4599-a26f-a799167cc82f

{"cities":["cq","cd","bj"],"userName":"string"}

2.通過注解攔截權限范圍參數,并根據預授權范圍比較,回寫在授權范圍內的權限范圍參數

cities = ["cq","cd"]

3.通過參數傳遞到DAO層,在SQL語句中拼裝出查詢條件,實現數據的過濾

select * from order where city in ('cq','cd')

三、 實現步驟

1. 注解實現

注解的完整代碼,請詳見源代碼

1)創(chuàng)建注解

@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD})
@Documented
public @interface ScopeAuth {

    String token() default "AUTH_TOKEN";
    String scope() default "";
    String[] scopes() default {};
}

此注解為運行時RetentionPolicy.RUNTIME作用在方法上ElementType.METHOD

token:獲取識別唯一用戶的標識,與用戶數據權限存儲有關

scopescopes:預請求的數據權限范圍

2) AOP實現注解

public class ScopeAuthAdvice {
  
    @Around("@annotation(scopeAuth)")
    public Object before(ProceedingJoinPoint thisJoinPoint, ScopeAuth scopeAuth) throws Throwable {
        // ... 省略過程
        // 獲取token
        String authToken = getToken(args, scopeAuth.token(), methodSignature.getMethod());
            // 回寫范圍參數
        setScope(scopeAuth.scope(), methodSignature, args, authToken);
        
        return thisJoinPoint.proceed();
    }

    /**
     * 設置范圍
     */
    private void setScope(String scope, MethodSignature methodSignature, Object[] args, String authToken) {
        // 獲取請求范圍
        Set<String> requestScope = getRequestScope(args, scope, methodSignature.getMethod());
        ScopeAuthAdapter adapter = new ScopeAuthAdapter(supplier);
        // 已授權范圍
        Set<String> authorizedScope = adapter.identifyPermissionScope(authToken, requestScope);
        // 回寫新范圍
        setRequestScope(args, scope, authorizedScope, methodSignature.getMethod());
    }

    /**
     * 回寫請求范圍
     */
    private void setRequestScope(Object[] args, String scopeName, Collection<String> scopeValues, Method method) {
        // 解析 SPEL 表達式
        if (scopeName.indexOf(SPEL_FLAG) == 0) {
            ParseSPEL.setMethodValue(scopeName, scopeValues, method, args);
        }
    }
}

此為演示代碼省略了過程,主要功能為通過token拿到預先授權的數據范圍,再與本次請求的范圍做交集,最后回寫回原參數。

過程中用到了較多的SPEL表達式,用于計算表達式結果,具體請參考ParseSPEL文件

3)權限范圍交集計算

public class ScopeAuthAdapter {

    private final AuthQuerySupplier supplier;

    public ScopeAuthAdapter(AuthQuerySupplier supplier) {
        this.supplier = supplier;
    }

    /**
     * 驗證權限范圍
     * @param token
     * @param requestScope
     * @return
     */
    public Set<String> identifyPermissionScope(String token, Set<String> requestScope) {
        Set<String> authorizeScope = supplier.queryScope(token);

        String ALL_SCOPE = "AUTH_ALL";
        String USER_ALL = "USER_ALL";

        if (authorizeScope == null) {
            return null;
        }

        if (authorizeScope.contains(ALL_SCOPE)) {
            // 如果是全開放則返回請求范圍
            return requestScope;
        }

        if (requestScope == null) {
            return null;
        }

        if (requestScope.contains(USER_ALL)){
            // 所有授權的范圍
            return authorizeScope;
        }

        // 移除不同的元素
        requestScope.retainAll(authorizeScope);

        return requestScope;
    }
}

此處為了方便設置,有兩個關鍵字范圍

  • AUTH_ALL:預設所有范圍,全開放的意思,為數據庫預先設置值,請求傳什么值都通過
  • USER_ALL:請求所有授權的范圍,請求時傳此值則會以數據庫預設值為準

4) spring.factories自動導入類配置

org.springframework.boot.autoconfigure.AutoConfigurationImportSelector=\
  fun.barryhome.cloud.annotation.ScopeAuthAdvice

如果注解功能是單獨項目存在,在使用時有可能會存在找不到引入文件的問題,可通過此配置文件自動載入需要初始化的類

2. 注解使用

@ScopeAuth(scopes = {"#orderDTO.cities"}, token = "#request.getHeader(\"X-User-Name\")")
@PostMapping(value = "/query")
public String query(@RequestBody OrderDTO orderDTO, HttpServletRequest request) {
    return Arrays.toString(orderDTO.getCities());
}

在需要使用數據權限的controller方法上增加@ScopeAuth注解

scopes = {"#orderDTO.cities"}:表示取輸入參數orderDTO的cities值,這里是表達式必須加#

實際開發(fā)過程中,需要將orderDTO.getCities()帶入后續(xù)邏輯中,在DAO層將此拼裝在SQL中,以實現數據過濾功能

3. 實現AuthStoreSupplier

AuthStoreSupplier接口為數據權限的存儲接口,與AuthQuerySupplier配合使用,可按實際情況實現

此接口為非必要接口,可由數據庫或Redis存儲(推薦),一般在登錄的同時保存在Redis中

4. 實現AuthQuerySupplier

AuthQuerySupplier接口為數據權限查詢接口,可按存儲方法進行查詢,推薦使用Redis

@Component
public class RedisAuthQuerySupplier implements AuthQuerySupplier {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 查詢范圍
     */
    @Override
    public Set<String> queryScope(String key) {
        String AUTH_USER_KEY = "auth:logic:user:%s";
        String redisKey = String.format(AUTH_USER_KEY, key);

        List<String> range = redisTemplate.opsForList().range(redisKey, 0, -1);

        if (range != null) {
            return new HashSet<>(range);
        } else {
            return null;
        }
    }
}

在分布式結構里,也可將此實現提出到權限模塊,采用遠程調用方式,進一步解耦

5. 開啟數據權限

@EnableScopeAuth
@EnableDiscoveryClient
@SpringBootApplication
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}

四、 綜述

至此數據權限功能就實現了。在微服務器架構中為了實現功能的復用,將注解的創(chuàng)建和AuthQuerySupplier的實現提取到公共模塊中,那么在具體的使用模塊就簡單得多了。只需增加@ScopeAuth注解,配置好查詢方法就可以使用。

五、源代碼

文中代碼由于篇幅原因有一定省略并不是完整邏輯,如有興趣請Fork源代碼

到此這篇關于SpringCloud 微服務數據權限控制的實現的文章就介紹到這了,更多相關SpringCloud內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • java中關于移位運算符的demo與總結(推薦)

    java中關于移位運算符的demo與總結(推薦)

    下面小編就為大家?guī)硪黄猨ava中關于移位運算符的demo與總結(推薦)。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-05-05
  • 詳解Java中NullPointerException異常的原因詳解以及解決方法

    詳解Java中NullPointerException異常的原因詳解以及解決方法

    這篇文章主要介紹了詳解Java中NullPointerException異常的原因詳解以及解決方法。文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-08-08
  • Java四舍五入時保留指定小數位數的五種方式

    Java四舍五入時保留指定小數位數的五種方式

    這篇文章主要介紹了Java四舍五入時保留指定小數位數的五種方式,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-09-09
  • Java遞歸基礎與遞歸的宏觀語意實例分析

    Java遞歸基礎與遞歸的宏觀語意實例分析

    這篇文章主要介紹了Java遞歸基礎與遞歸的宏觀語意,結合實例形式分析了java遞歸的相關原理、操作技巧與注意事項,需要的朋友可以參考下
    2020-03-03
  • Spring mvc Controller和RestFul原理解析

    Spring mvc Controller和RestFul原理解析

    這篇文章主要介紹了Spring mvc Controller和RestFul原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-03-03
  • Java基礎知識總結之繼承

    Java基礎知識總結之繼承

    這一篇我們來學習面向對象的第二個特征——繼承,文中有非常詳細的基礎知識總結,對正在學習java的小伙伴們很有幫助,需要的朋友可以參考下
    2021-06-06
  • Feign?請求動態(tài)URL方式

    Feign?請求動態(tài)URL方式

    這篇文章主要介紹了Feign?請求動態(tài)URL方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • Java實現斗地主最簡代碼實例

    Java實現斗地主最簡代碼實例

    在本篇文章里小編給各位分享的是關于Java實現斗地主最簡代碼實例,有興趣的朋友們可以參考下。
    2020-05-05
  • Spring Boot開啟遠程調試的方法

    Spring Boot開啟遠程調試的方法

    這篇文章主要介紹了Spring Boot開啟遠程調試的方法,幫助大家更好的理解和使用Spring Boot框架,感興趣的朋友可以了解下
    2020-10-10
  • JUnit4 Hamcrest匹配器常用方法總結

    JUnit4 Hamcrest匹配器常用方法總結

    這篇文章主要介紹了JUnit4 Hamcrest匹配器常用方法總結,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-11-11

最新評論