自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

聊聊網(wǎng)關(guān)Restful接口攔截

網(wǎng)絡(luò) 通信技術(shù)
本章內(nèi)容我們就來解決這個Restful接口攔截的問題,使其能支持精細化的權(quán)限控制。

[[375844]]

本文轉(zhuǎn)載自微信公眾號「JAVA日知錄」,作者單一色調(diào)。轉(zhuǎn)載本文請聯(lián)系JAVA日知錄公眾號。

前言

之前在 集成RBAC授權(quán) 的文章中提到了SpringCloud可以「基于路徑匹配器授權(quán)」在網(wǎng)關(guān)層進行用戶權(quán)限校驗,這種方式的實現(xiàn)原理是Springcloud Gateway接受到請求后根據(jù) ReactiveAuthorizationManager#check(Mono authenticationMono, AuthorizationContext authorizationContext) 方法基于 AntPathMatcher校驗當前訪問的URL是否在用戶擁有的權(quán)限URL中,如果能匹配上則說明擁有訪問權(quán)限并放行到后端服務(wù),否則提示用戶無訪問權(quán)限。

具體實現(xiàn)方式在上面文章中有闡述,如果有不清楚的可以再次查閱。文章地址:

http://javadaily.cn/articles/2020/08/07/1596772909329.html

不過之前的實現(xiàn)方式有個問題,就是不支持restful風(fēng)格的url路徑。

例如一個微服務(wù)有如下API

  • GET /v1/pb/user
  • POST /v1/pb/user
  • PUT /v1/pb/user

這樣在網(wǎng)關(guān)通過 request.getURI().getPath()方法獲取到用戶請求路徑的時候都是同一個地址,給一個用戶授予 /v1/pb/user權(quán)限后他就擁有了 GET、PUT、POST三種不同權(quán)限,很顯然這樣不能滿足精細權(quán)限控制。本章內(nèi)容我們就來解決這個Restful接口攔截的問題,使其能支持精細化的權(quán)限控制。

場景演示

我們看下實際的案例,演示下這種場景。在 account-service模塊下增加一個博客用戶管理功能,有如下的接口方法:

接口URL HTTP方法 接口說明
/blog/user POST 保存用戶
/blog/user/{id} GET 查詢用戶
/blog/user/{id} DELETE 刪除用戶
/blog/user/{id} PUT 更新用戶信息

然后我們在 sys_permission表中添加2個用戶權(quán)限,再將其授予給用戶角色

在網(wǎng)關(guān)層的校驗方法中可以看到已經(jīng)增加了2個權(quán)限

由于DELETE 和 PUT對應(yīng)的權(quán)限路徑都是 /blog/user/{id},這樣就是當給用戶授予了查詢權(quán)限后此用戶也擁有了刪除和更新的權(quán)限。

解決方案

看到這里大部分同學(xué)應(yīng)該想到了,要想實現(xiàn)Restful風(fēng)格的精細化權(quán)限管理單單通過URL路徑是不行的,需要搭配Method一起使用。

最關(guān)鍵的點就是「需要給權(quán)限表加上方法字段,然后在網(wǎng)關(guān)校驗的時候即判斷請求路徑又匹配請求方法?!?實現(xiàn)步驟如下:

修改權(quán)限表,新增方法字段

  • 在loadUserByUsername()方法構(gòu)建用戶權(quán)限的時候?qū)?quán)限對應(yīng)的Method也拼接在權(quán)限上,關(guān)鍵代碼如下:
  1. @Override 
  2. public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException { 
  3.  //獲取本地用戶 
  4.  SysUser sysUser = sysUserMapper.selectByUserName(userName); 
  5.  if(sysUser != null){ 
  6.   //獲取當前用戶的所有角色 
  7.   List<SysRole> roleList = sysRoleService.listRolesByUserId(sysUser.getId()); 
  8.   sysUser.setRoles(roleList.stream().map(SysRole::getRoleCode).collect(Collectors.toList())); 
  9.   List<Integer> roleIds = roleList.stream().map(SysRole::getId).collect(Collectors.toList()); 
  10.   //獲取所有角色的權(quán)限 
  11.   List<SysPermission> permissionList = sysPermissionService.listPermissionsByRoles(roleIds); 
  12.   //拼接method 
  13.   List<String> permissionUrlList = permissionList.stream() 
  14.                     .map(item -> "["+item.getMethod()+"]"+item.getUrl()) 
  15.                     .collect(Collectors.toList()); 
  16.   sysUser.setPermissions(permissionUrlList); 
  17.   //構(gòu)建oauth2的用戶 
  18.   return buildUserDetails(sysUser); 
  19.  }else
  20.   throw  new UsernameNotFoundException("用戶["+userName+"]不存在"); 
  21.  } 

通過上面的代碼構(gòu)建的用戶權(quán)限如下:

  • [GET]/account-service/blog/user/{id}
  • [POST]/account-service/blog/user

可以通過代碼調(diào)試查看:

  • 權(quán)限校驗方法AccessManager#check(),校驗[MEHOTD]RequestPath 格式

@Override

  1. @Override 
  2. public Mono<AuthorizationDecision> check(Mono<Authentication> authenticationMono, AuthorizationContext authorizationContext) { 
  3.  ServerWebExchange exchange = authorizationContext.getExchange(); 
  4.  ServerHttpRequest request = exchange.getRequest(); 
  5.  //請求資源 
  6.  String requestPath = request.getURI().getPath(); 
  7.  
  8.  //拼接method 
  9.  String methodPath = "["+request.getMethod()+"]" + requestPath; 
  10.  
  11.  // 1. 對應(yīng)跨域的預(yù)檢請求直接放行 
  12.  if(request.getMethod() == HttpMethod.OPTIONS){ 
  13.   return Mono.just(new AuthorizationDecision(true)); 
  14.  } 
  15.  
  16.  // 是否直接放行 
  17.  if (permitAll(requestPath)) { 
  18.   return Mono.just(new AuthorizationDecision(true)); 
  19.  } 
  20.  
  21.  return authenticationMono.map(auth -> new AuthorizationDecision(checkAuthorities(auth, methodPath))) 
  22.    .defaultIfEmpty(new AuthorizationDecision(false)); 
  23.  

校驗方法 checkAuthorities():

  1. private boolean checkAuthorities(Authentication auth, String requestPath) { 
  2.  if(auth instanceof OAuth2Authentication){ 
  3.   OAuth2Authentication authentication = (OAuth2Authentication) auth; 
  4.   String clientId = authentication.getOAuth2Request().getClientId(); 
  5.   log.info("clientId is {}",clientId); 
  6.   //用戶的權(quán)限集合 
  7.   Collection<? extends GrantedAuthority> authorities = auth.getAuthorities(); 
  8.  
  9.   return authorities.stream() 
  10.     .map(GrantedAuthority::getAuthority) 
  11.     //ROLE_開頭的為角色,需要過濾掉 
  12.     .filter(item -> !item.startsWith(CloudConstant.ROLE_PREFIX)) 
  13.     .anyMatch(permission -> ANT_PATH_MATCHER.match(permission, requestPath)); 
  14.  } 
  15.  
  16.  return true
  • 這樣當請求Delete方法時就會提示沒有權(quán)限

這里還有另外一種方案,實現(xiàn)的原理跟上面差不多,只簡單提一下。

首先還是得在權(quán)限表中新增METHOD字段,這是必須的。

然后項目中使用的權(quán)限類是 SimpleGrantedAuthority,這個只能存儲一個權(quán)限字段,我們可以自定義一個權(quán)限實體類,讓其可以存儲url 和 method。

  1. @Data 
  2. public class MethodGrantedAuthority implements GrantedAuthority { 
  3.  
  4.     private String method; 
  5.     private String url; 
  6.  
  7.     public MethodGrantedAuthority(String method, String url){ 
  8.         this.method = method; 
  9.         this.url = url; 
  10.     } 
  11.  
  12.     @Override 
  13.     public String getAuthority() { 
  14.         return "["+method+"]" + url; 
  15.     } 

在 UserDetailServiceImpl中構(gòu)建用戶權(quán)限時使用自定義的 MethodGrantedAuthority

網(wǎng)關(guān)層校驗的方法還是需要跟上面一樣,既校驗Method 又 校驗 URL。

 

責(zé)任編輯:武曉燕 來源: JAVA日知錄
相關(guān)推薦

2024-03-05 10:09:16

restfulHTTPAPI

2021-03-16 06:55:49

Server4認證網(wǎng)關(guān)

2020-07-07 07:54:01

API網(wǎng)關(guān)微服務(wù)

2023-07-26 07:13:55

函數(shù)接口Java 8

2021-09-18 09:45:33

前端接口架構(gòu)

2023-11-20 08:01:38

并發(fā)處理數(shù)Tomcat

2020-05-27 08:05:33

MybatisMapper接口

2021-04-02 12:37:53

RestfulAPI接口架構(gòu)

2022-02-08 23:59:12

USB接口串行

2022-11-17 07:43:13

2022-01-26 00:05:00

接口Spring管理器

2021-05-25 11:13:48

SSL證書過期微軟Microsoft E

2018-04-24 09:05:09

容器存儲接口

2024-07-30 09:35:00

2022-06-10 13:03:44

接口重試while

2021-11-18 08:20:22

接口索引SQL

2020-05-06 22:07:53

UbuntuLinux操作系統(tǒng)

2024-11-27 08:47:12

2022-02-21 13:27:11

接口性能優(yōu)化索引命令

2023-11-29 09:04:00

前端接口
點贊
收藏

51CTO技術(shù)棧公眾號