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

SpringCloud?微服務(wù)數(shù)據(jù)權(quán)限控制的實(shí)現(xiàn)

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

舉個(gè)例子:

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

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

一、 整體架構(gòu)

數(shù)據(jù)權(quán)限為作一個(gè)注解的形式掛在每一個(gè)需要數(shù)據(jù)權(quán)限控制的Controller上,由于和具體的程序邏輯有關(guān)故有一定的入侵性,且需要數(shù)據(jù)庫配合使用。

二、 實(shí)現(xiàn)流程

1.瀏覽器傳帶查詢權(quán)限范圍參數(shù)訪問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.通過注解攔截權(quán)限范圍參數(shù),并根據(jù)預(yù)授權(quán)范圍比較,回寫在授權(quán)范圍內(nèi)的權(quán)限范圍參數(shù)

cities = ["cq","cd"]

3.通過參數(shù)傳遞到DAO層,在SQL語句中拼裝出查詢條件,實(shí)現(xiàn)數(shù)據(jù)的過濾

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

三、 實(shí)現(xiàn)步驟

1. 注解實(shí)現(xiàn)

注解的完整代碼,請?jiān)斠?a rel="external nofollow" target="_blank">源代碼

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 {};
}

此注解為運(yùn)行時(shí)RetentionPolicy.RUNTIME作用在方法上ElementType.METHOD

token:獲取識別唯一用戶的標(biāo)識,與用戶數(shù)據(jù)權(quán)限存儲有關(guān)

scope,scopes:預(yù)請求的數(shù)據(jù)權(quán)限范圍

2) AOP實(shí)現(xiàn)注解

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

    /**
     * 設(shè)置范圍
     */
    private void setScope(String scope, MethodSignature methodSignature, Object[] args, String authToken) {
        // 獲取請求范圍
        Set<String> requestScope = getRequestScope(args, scope, methodSignature.getMethod());
        ScopeAuthAdapter adapter = new ScopeAuthAdapter(supplier);
        // 已授權(quán)范圍
        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 表達(dá)式
        if (scopeName.indexOf(SPEL_FLAG) == 0) {
            ParseSPEL.setMethodValue(scopeName, scopeValues, method, args);
        }
    }
}

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

過程中用到了較多的SPEL表達(dá)式,用于計(jì)算表達(dá)式結(jié)果,具體請參考ParseSPEL文件

3)權(quán)限范圍交集計(jì)算

public class ScopeAuthAdapter {

    private final AuthQuerySupplier supplier;

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

    /**
     * 驗(yàn)證權(quán)限范圍
     * @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)){
            // 所有授權(quán)的范圍
            return authorizeScope;
        }

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

        return requestScope;
    }
}

此處為了方便設(shè)置,有兩個(gè)關(guān)鍵字范圍

  • AUTH_ALL:預(yù)設(shè)所有范圍,全開放的意思,為數(shù)據(jù)庫預(yù)先設(shè)置值,請求傳什么值都通過
  • USER_ALL:請求所有授權(quán)的范圍,請求時(shí)傳此值則會以數(shù)據(jù)庫預(yù)設(shè)值為準(zhǔn)

4) spring.factories自動(dòng)導(dǎo)入類配置

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

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

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());
}

在需要使用數(shù)據(jù)權(quán)限的controller方法上增加@ScopeAuth注解

scopes = {"#orderDTO.cities"}:表示取輸入?yún)?shù)orderDTO的cities值,這里是表達(dá)式必須加#

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

3. 實(shí)現(xiàn)AuthStoreSupplier

AuthStoreSupplier接口為數(shù)據(jù)權(quán)限的存儲接口,與AuthQuerySupplier配合使用,可按實(shí)際情況實(shí)現(xiàn)

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

4. 實(shí)現(xiàn)AuthQuerySupplier

AuthQuerySupplier接口為數(shù)據(jù)權(quán)限查詢接口,可按存儲方法進(jìn)行查詢,推薦使用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;
        }
    }
}

在分布式結(jié)構(gòu)里,也可將此實(shí)現(xiàn)提出到權(quán)限模塊,采用遠(yuǎn)程調(diào)用方式,進(jìn)一步解耦

5. 開啟數(shù)據(jù)權(quán)限

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

四、 綜述

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

五、源代碼

文中代碼由于篇幅原因有一定省略并不是完整邏輯,如有興趣請F(tuán)ork源代碼

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

相關(guān)文章

  • Java日期格式化如何避免YYYY引發(fā)的時(shí)間異常

    Java日期格式化如何避免YYYY引發(fā)的時(shí)間異常

    在編程中,日期格式化是一個(gè)常見的任務(wù),使用不同的格式化選項(xiàng)可能會導(dǎo)致一些意外的結(jié)果,下面我們就來學(xué)習(xí)一下Java如何避免YYYY引發(fā)的時(shí)間異常吧
    2023-11-11
  • Java鏈表數(shù)據(jù)結(jié)構(gòu)及其簡單使用方法解析

    Java鏈表數(shù)據(jù)結(jié)構(gòu)及其簡單使用方法解析

    這篇文章主要介紹了Java鏈表數(shù)據(jù)結(jié)構(gòu)及其簡單使用方法解析,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-07-07
  • Swagger文檔自動(dòng)生成PDF/HTML/Word解決方案詳細(xì)指南

    Swagger文檔自動(dòng)生成PDF/HTML/Word解決方案詳細(xì)指南

    本指南詳細(xì)介紹了Swagger?YAML/JSON定義、Swagger?UI的使用、Swagger轉(zhuǎn)為Markdown格式以及Markdown轉(zhuǎn)為PDF/HTML/Word的過程,包括工具如Pandoc的運(yùn)用,并提供了一個(gè)Spring?Boot應(yīng)用集成Swagger2和Swagger2Markup的示例,闡述了API文檔的生成流程,感興趣的朋友一起看看吧
    2025-08-08
  • Java圖形化編程之JFrame疫苗接種系統(tǒng)詳解

    Java圖形化編程之JFrame疫苗接種系統(tǒng)詳解

    GUI圖形界面設(shè)計(jì)是用戶和程序交互的工具,用戶通過圖形界面控制程序事件的發(fā)生。首先介紹Swing的基本體系結(jié)構(gòu),這是底層
    2021-09-09
  • springboot學(xué)習(xí)之Thymeleaf模板引擎及原理介紹

    springboot學(xué)習(xí)之Thymeleaf模板引擎及原理介紹

    本文主要介紹一下SpringBoot給我們推薦的Thymeleaf模板引擎,這模板引擎呢,是一個(gè)高級語言的模板引擎,他的這個(gè)語法更簡單而且功能更強(qiáng)大,對springboot?Thymeleaf模板引擎相關(guān)知識感興趣的朋友一起看看吧
    2022-02-02
  • 啟用設(shè)置org.slf4j.Logger打印并輸出日志方式

    啟用設(shè)置org.slf4j.Logger打印并輸出日志方式

    這篇文章主要介紹了啟用設(shè)置org.slf4j.Logger打印并輸出日志方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • Mybatis框架中Interceptor接口的使用說明

    Mybatis框架中Interceptor接口的使用說明

    這篇文章主要介紹了Mybatis框架中Interceptor接口的使用說明,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java使用Spring JdbcTemplate向in語句中傳遞參數(shù)的教程詳解

    Java使用Spring JdbcTemplate向in語句中傳遞參數(shù)的教程詳解

    這篇文章主要給大家介紹Java如何使用Spring JdbcTemplate向in語句中傳遞參數(shù),文中有詳細(xì)的流程步驟和代碼示例,需要的朋友可以參考下
    2023-07-07
  • java學(xué)生信息管理系統(tǒng)設(shè)計(jì)

    java學(xué)生信息管理系統(tǒng)設(shè)計(jì)

    這篇文章主要為大家詳細(xì)介紹了java學(xué)生信息管理系統(tǒng)設(shè)計(jì),學(xué)生信息添加進(jìn)入數(shù)據(jù)庫的事務(wù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • 深入理解Java中的String(示例詳解)

    深入理解Java中的String(示例詳解)

    文章詳細(xì)介紹了Java中String類的特點(diǎn)、用途、主要方法以及常見用法,String類是不可變的,具有字符串常量池,特定的內(nèi)存結(jié)構(gòu),并隨JDK版本更新而優(yōu)化,它廣泛用于表示和處理文本數(shù)據(jù),并在內(nèi)存管理和性能優(yōu)化方面表現(xiàn)出色,感興趣的朋友一起看看吧
    2025-03-03

最新評論