偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

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

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

[[375844]]

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

前言

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

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

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

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

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

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

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

場(chǎng)景演示

我們看下實(shí)際的案例,演示下這種場(chǎng)景。在 account-service模塊下增加一個(gè)博客用戶(hù)管理功能,有如下的接口方法:

接口URL HTTP方法 接口說(shuō)明
/blog/user POST 保存用戶(hù)
/blog/user/{id} GET 查詢(xún)用戶(hù)
/blog/user/{id} DELETE 刪除用戶(hù)
/blog/user/{id} PUT 更新用戶(hù)信息

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

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

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

解決方案

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

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

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

  • 在loadUserByUsername()方法構(gòu)建用戶(hù)權(quán)限的時(shí)候?qū)?quán)限對(duì)應(yīng)的Method也拼接在權(quán)限上,關(guān)鍵代碼如下:
  1. @Override 
  2. public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException { 
  3.  //獲取本地用戶(hù) 
  4.  SysUser sysUser = sysUserMapper.selectByUserName(userName); 
  5.  if(sysUser != null){ 
  6.   //獲取當(dāng)前用戶(hù)的所有角色 
  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的用戶(hù) 
  18.   return buildUserDetails(sysUser); 
  19.  }else
  20.   throw  new UsernameNotFoundException("用戶(hù)["+userName+"]不存在"); 
  21.  } 

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

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

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

  • 權(quán)限校驗(yàn)方法AccessManager#check(),校驗(yàn)[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.  //請(qǐng)求資源 
  6.  String requestPath = request.getURI().getPath(); 
  7.  
  8.  //拼接method 
  9.  String methodPath = "["+request.getMethod()+"]" + requestPath; 
  10.  
  11.  // 1. 對(duì)應(yīng)跨域的預(yù)檢請(qǐng)求直接放行 
  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.  

校驗(yàn)方法 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.   //用戶(hù)的權(quán)限集合 
  7.   Collection<? extends GrantedAuthority> authorities = auth.getAuthorities(); 
  8.  
  9.   return authorities.stream() 
  10.     .map(GrantedAuthority::getAuthority) 
  11.     //ROLE_開(kāi)頭的為角色,需要過(guò)濾掉 
  12.     .filter(item -> !item.startsWith(CloudConstant.ROLE_PREFIX)) 
  13.     .anyMatch(permission -> ANT_PATH_MATCHER.match(permission, requestPath)); 
  14.  } 
  15.  
  16.  return true
  • 這樣當(dāng)請(qǐng)求Delete方法時(shí)就會(huì)提示沒(méi)有權(quán)限

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

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

然后項(xiàng)目中使用的權(quán)限類(lèi)是 SimpleGrantedAuthority,這個(gè)只能存儲(chǔ)一個(gè)權(quán)限字段,我們可以自定義一個(gè)權(quán)限實(shí)體類(lèi),讓其可以存儲(chǔ)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)建用戶(hù)權(quán)限時(shí)使用自定義的 MethodGrantedAuthority

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

 

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

2024-03-05 10:09:16

restfulHTTPAPI

2021-03-16 06:55:49

Server4認(rèn)證網(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

2020-05-27 08:05:33

MybatisMapper接口

2021-09-18 09:45:33

前端接口架構(gòu)

2023-11-20 08:01:38

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

2022-02-08 23:59:12

USB接口串行

2022-01-26 00:05:00

接口Spring管理器

2022-11-17 07:43:13

2021-04-02 12:37:53

RestfulAPI接口架構(gòu)

2018-04-24 09:05:09

容器存儲(chǔ)接口

2021-05-25 11:13:48

SSL證書(shū)過(guò)期微軟Microsoft E

2024-07-30 09:35:00

2020-05-06 22:07:53

UbuntuLinux操作系統(tǒng)

2022-06-10 13:03:44

接口重試while

2021-11-18 08:20:22

接口索引SQL

2025-05-26 03:15:00

接口高可用框架

2024-11-27 08:47:12

2022-02-21 13:27:11

接口性能優(yōu)化索引命令
點(diǎn)贊
收藏

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