日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

GitHub轻松阅读微服务实战项目流程详解【第二天:API网关的设计与实现】

發(fā)布時間:2024/10/5 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 GitHub轻松阅读微服务实战项目流程详解【第二天:API网关的设计与实现】 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Two Day

  • 1.配置文件精解
    • (1)bootstrap.yml文件
    • (2)nacos中關(guān)于gateway的配置信息
    • (3)applicaton.properties白名單配置
  • 2.代碼詳解
    • (1)IP限流
    • (2)白名單
    • (3)Jwt工具類驗證token的有效性
    • (4)網(wǎng)關(guān)層面快速失敗返回接口
    • (5)微服務(wù)安全認(rèn)證流程
    • (6)身份認(rèn)證過濾器實現(xiàn)


github地址:https://github.com/Zealon159/light-reading-cloud


該網(wǎng)關(guān)層面使用Spring GateWay進行實現(xiàn)。

1.配置文件精解

(1)bootstrap.yml文件

spring:application:# 服務(wù)邏輯名稱name: light-reading-cloud-gatewaycloud:nacos:# 配置中心config:server-addr: xxxxxxfile-extension: ymlrefresh: trueshared-dataids: light-reading-cloud-gateway.yml #Data IDnamespace: 4d109a4d-f34d-4e86-9e39-c2d36db24b00 #命名空間# 注冊中心discovery:server-addr: xxxxxnamespace: 4d109a4d-f34d-4e86-9e39-c2d36db24b00

(2)nacos中關(guān)于gateway的配置信息

server:port: 8010spring:application:# 服務(wù)邏輯名稱name: light-reading-cloud-gatewaycloud:gateway:discovery:locator:enabled: true #開啟gateway的注冊和發(fā)現(xiàn)lowerCaseServiceId: true #將請求路徑中的服務(wù)名小寫,因為服務(wù)注冊時,Nacos將其轉(zhuǎn)換成大寫了routes: #路由匹配- id: book-center-rpc uri: lb://light-reading-cloud-book #服務(wù)地址predicates: #斷言,匹配路徑和請求方式- Path=/book/**- Method=GETfilters:# 降級配置- name: Hystrixargs:name: fallbackcmdfallbackUri: forward:/fallback #失敗了直接跳轉(zhuǎn)到該路據(jù),這個接口是用戶失敗后快速返回的# 限流配置- name: RequestRateLimiterargs:redis-rate-limiter.replenishRate: 3 # 每秒允許處理的請求數(shù)量redis-rate-limiter.burstCapacity: 5 # 每秒最大處理的請求數(shù)量key-resolver: "#{@ipKeyResolver}" # 限流策略,對應(yīng)策略的Bean,在gateway配置了該IP的限流策略- id: homepage-rpcuri: lb://light-reading-cloud-homepagepredicates:- Path=/index/**filters:# 降級配置- name: Hystrixargs:name: fallbackcmdfallbackUri: forward:/fallback# 限流配置- name: RequestRateLimiterargs:redis-rate-limiter.replenishRate: 3redis-rate-limiter.burstCapacity: 5key-resolver: "#{@ipKeyResolver}"- id: account-center-rpcuri: lb://light-reading-cloud-accountpredicates:- Path=/account/**filters:# 降級配置- name: Hystrixargs:name: fallbackcmdfallbackUri: forward:/fallback# 限流配置- name: RequestRateLimiterargs:redis-rate-limiter.replenishRate: 3redis-rate-limiter.burstCapacity: 5key-resolver: "#{@ipKeyResolver}"hystrix:threadpool:default:coreSize: 20 #并發(fā)執(zhí)行的最大線程數(shù),默認(rèn)10maxQueueSize: 1000 #BlockingQueue的最大隊列數(shù),默認(rèn)值-1queueSizeRejectionThreshold: 400 ribbon:eager-load:enabled: true #開啟Ribbon的饑餓模式, 用于點對點直連問題clients: light-reading-cloud-account,light-reading-cloud-book,light-reading-cloud-homepage

(3)applicaton.properties白名單配置

system.properties=/account/user/register,/account/user/login

這個本地application.properties是配置的白名單信息,后面會在配置類中進行加載。

2.代碼詳解

(1)IP限流

@Configuration public class RedisRateLimiterConfig {/*** 按客戶端IP限流* Lambda表達式或者匿名函數(shù)都可以快速實現(xiàn)* @return*/@Beanpublic KeyResolver ipKeyResolver() { return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());} }

這個ipKeyResolver方法是在gateway配置文件中引用的

(2)白名單

@Data @Component public class SystemPropertiesConfig {/** 請求白名單,引用application.preperties中的屬性 */@Value("${system.properties}")private String whitelist; }

(3)Jwt工具類驗證token的有效性

Token比較適用于微服務(wù)的安全認(rèn)證,JWT是一種安全認(rèn)證規(guī)范,token中存儲了用戶信息,只有在服務(wù)端才能根據(jù)密鑰進行解密。

public class JwtUtil {/*** 身份認(rèn)證* @param jwt 令牌* @return 成功狀態(tài)返回200,其它均為失敗*/public static Result<User> validationToken(String jwt) {try {//解析JWT字符串中的數(shù)據(jù),并進行最基礎(chǔ)的驗證Claims claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(jwt).getBody();//如果解析成功,將其封裝到User返回User user = new User();user.setUuid(claims.get("uuid").toString());user.setLoginName(claims.get("loginName").toString());user.setNickName(claims.get("nickName").toString());if (claims.get("phoneNumber") != null) {user.setPhoneNumber(claims.get("phoneNumber").toString());}user.setId(Integer.parseInt(claims.get("id").toString()));user.setHeadImgUrl(claims.get("headImgUrl").toString());return ResultUtil.success(user);} catch (ExpiredJwtException e) {// 已過期令牌return ResultUtil.authExpired();} catch (SignatureException e) {// 偽造令牌return ResultUtil.unAuthorized();} catch (Exception e) {// 系統(tǒng)錯誤return ResultUtil.unAuthorized();}}}

(4)網(wǎng)關(guān)層面快速失敗返回接口

public class FallbackController {@GetMapping("/fallback")public Result fallback() {return ResultUtil.fail();} }

(5)微服務(wù)安全認(rèn)證流程

常用的認(rèn)證方式主要有三種:Session、HTTP Basic Authentication 和 Token。

  • session 是認(rèn)證中最常用的一種方式,也是最簡單的。用戶登錄后將信息存儲在后端,客戶端則通過 Cookie 中的 SessionId 來標(biāo)識對應(yīng)的用戶。
  • HTTP Basic Authentication 也就是 HTTP 基本認(rèn)證,它是 HTTP 1.0 提出的一種認(rèn)證機制。HTTP 基本認(rèn)證的原理是客戶端在請求時會在請求頭中增加 Authorization,Authorization 是用戶名和密碼用 Base64 加密后的內(nèi)容。服務(wù)端獲取 Authorization Header 中的用戶名與密碼進行驗證。
  • Token 中會存儲用戶的信息,然后通過加密算法進行加密,只有服務(wù)端才能解密,服務(wù)端拿到 Token 后進行解密獲取用戶信息。

Token更適用于微服務(wù)的安全認(rèn)證,本項目采用了token這種認(rèn)證方式,并基于JWT的安全認(rèn)證規(guī)范。

jwt是一種認(rèn)證規(guī)范,它允許我們通過jwt在用戶和服務(wù)器之間傳遞可靠的信息。在通信過程中進行身份認(rèn)證

Ⅰ.用戶進行登錄時,將用戶名和密碼提交給認(rèn)證服務(wù)器,服務(wù)器會驗證用戶提交信息的合法性,如果驗證成功,則會返回一個token,客戶端將token保存起來
Ⅱ.用戶再次請求服務(wù)器時,一般會將token放到請求頭中。當(dāng)請求達到網(wǎng)關(guān)后,會在網(wǎng)關(guān)中對token進行校驗;如果校驗成功,網(wǎng)關(guān)會將其轉(zhuǎn)發(fā)到后端服務(wù)中,轉(zhuǎn)發(fā)時會將用戶信息一并傳遞過去,這樣后端服務(wù)就不用再進行校驗了。

(1)網(wǎng)關(guān)是唯一的入口,所以微服務(wù)之間的請求就不需要再進行認(rèn)證。
(2)有些請求是不需要進行認(rèn)證的,所以我們加入了白名單進行處理。
(3)jwt的認(rèn)證過程主要是加密,而加密會耗費CPU的運算資源。如果請求量過大,可以將token緩存起來,這樣可以提高網(wǎng)關(guān)服務(wù)器CPU的性能。

(6)身份認(rèn)證過濾器實現(xiàn)

對于認(rèn)證過濾器實現(xiàn)類GlobalFilter和Ordered接口
1.GlobalFilter是gateway中的一個全局過濾器
2.我們知道gateway中的核心由一個過濾器鏈組成,這個過濾器鏈中的一個個過濾器是由Ordered進行排序的,數(shù)值越小越靠前執(zhí)行。
3.ServerWebExchange是gateway中的一個網(wǎng)絡(luò)交換器,它的內(nèi)部封裝了HTTP請求信息和響應(yīng)信息,我們可以在Filter中根據(jù)這個ServerWebExchange對請求信息或者響應(yīng)信息進行攔截,然后進行響應(yīng)的操作。
4.consumer是Java8提供了一個消費性函數(shù)式接口,對此我們可以通過lambda快速向請求頭中加入解析后的用戶信息
5.一般情況下,請求和響應(yīng)中的信息是不能修改的,但gateway為我們提供類一個mutate方法,專門用來修改請求和響應(yīng)信息。由于我們通過ServerWebExchange進行數(shù)據(jù)交換的,所以我們可以先將信息追加到ServerHttpRequest中,然后再將ServerHttpRequest封裝到ServerWebExchange中。

/*** 身份認(rèn)證過濾器* @author: Ronin* @since: 2021/10/5* @email:* 統(tǒng)一認(rèn)證的實現(xiàn)方式是自定義實現(xiàn)全局過濾器,在過濾器里面可以處理白名單放行、認(rèn)證校驗、動態(tài)處理請求參數(shù)等*/ @Component public class AuthFilter implements GlobalFilter, Ordered {@Autowired //白名單配置類private SystemPropertiesConfig systemPropertiesConfig;@Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 白名單Path,獲取白名單,獲取配置文件中的白名單Set<String> whiteList = this.getWhiteList();//獲取請求信息中的請求路徑String path = exchange.getRequest().getPath().toString();// 主頁接口、圖書接口正則匹配,如果匹配這兩個表示不用登錄就可以訪問boolean indexMatch = Pattern.matches("/index[^\\s]*", path);boolean bookMatch = Pattern.matches("/book/[^\\s]*", path);// 白名單接口、開放接口放行if (whiteList.contains(path) || bookMatch || indexMatch) {return chain.filter(exchange);}String[] segments = path.split("/");if (!whiteList.contains(segments[1])) {// 認(rèn)證--從請求頭中獲取token,通過jwt進行校驗String token = exchange.getRequest().getHeaders().getFirst("token");Result<User> result = JwtUtil.validationToken(token);if (result.getCode() == HttpCodeEnum.OK.getCode()) {// 認(rèn)證通過User user = result.getData();// 追加請求頭用戶信息Consumer<HttpHeaders> httpHeaders = httpHeader -> {httpHeader.set("userId",user.getId().toString());httpHeader.set("nickName",user.getNickName());};ServerHttpRequest serverHttpRequest = exchange.getRequest().mutate().headers(httpHeaders).build();exchange.mutate().request(serverHttpRequest).build();return chain.filter(exchange);}// 認(rèn)證過期、失敗,均返回401ServerHttpResponse response = exchange.getResponse();//將對象轉(zhuǎn)換為byte - json字符串byte[] bits = JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8);DataBuffer buffer = response.bufferFactory().wrap(bits);response.setStatusCode(HttpStatus.UNAUTHORIZED);// 指定編碼,否則在瀏覽器中會中文亂碼response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");return response.writeWith(Mono.just(buffer));}return chain.filter(exchange);}@Overridepublic int getOrder() {return 0; //數(shù)值越小,該過濾器越向前執(zhí)行}/*** 請求白名單* @return*/private Set<String> getWhiteList(){String whitelists = this.systemPropertiesConfig.getWhitelist();if (StringUtils.isEmpty(whitelists)) {return new HashSet<>();}Set<String> whiteList = new HashSet<>();String[] whiteArray = whitelists.split(",");for (int i = 0; i < whiteArray.length; i++) {whiteList.add(whiteArray[i]);}return whiteList;} }

總結(jié)

以上是生活随笔為你收集整理的GitHub轻松阅读微服务实战项目流程详解【第二天:API网关的设计与实现】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。