久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

SpringCloud微服務如何實現數據權限控制

154次閱讀
沒有評論

共計 4747 個字符,預計需要花費 12 分鐘才能閱讀完成。

SpringCloud 微服務如何實現數據權限控制,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

舉個例子:

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

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

一、整體架構

SpringCloud 微服務如何實現數據權限控制

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

二、實現流程

SpringCloud 微服務如何實現數據權限控制

瀏覽器傳帶查詢權限范圍參數訪問 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 }

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

cities = [cq , cd]

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

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

三、實現步驟 1. 注解實現

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

1)創建注解

@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:獲取識別唯一用戶的標識,與用戶數據權限存儲有關

scope,scopes:預請求的數據權限范圍

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 值,這里是表達式必須加 **#**

實際開發過程中,需要將 **orderDTO.getCities()** 帶入后續邏輯中,在 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);
 }
}

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

看完上述內容,你們掌握 SpringCloud 微服務如何實現數據權限控制的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注丸趣 TV 行業資訊頻道,感謝各位的閱讀!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-08-25發表,共計4747字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 博客| 资源县| 昌平区| 崇阳县| 扬州市| 绥中县| 新巴尔虎右旗| 新密市| 个旧市| 广昌县| 科技| 桦南县| 彩票| 蛟河市| 渑池县| 忻州市| 青海省| 墨竹工卡县| 肥西县| 肃南| 石首市| 龙山县| 图木舒克市| 昭平县| 延寿县| 宣化县| 五莲县| 永定县| 彰化市| 临桂县| 台中市| 定襄县| 延寿县| 白银市| 池州市| 安徽省| 措美县| 乌海市| 石门县| 和龙市| 甘南县|