日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

解決spring cloud gateway 獲取body內容并修改的問題

瀏覽:101日期:2023-07-30 09:53:58

之前寫過一篇文章,如何獲取body的內容。

Spring Cloud Gateway獲取body內容,不影響GET請求

確實能夠獲取所有body的內容了,不過今天終端同學調試接口的時候和我說,遇到了400的問題,報錯是這樣的HTTP method names must be tokens,搜了一下,都是說https引起的??晌业捻椖窟€沒用https,排除了。

想到是不是因為修改了body內容導致的問題,試著不修改body的內容,直接傳給微服務,果然沒有報錯了。

問題找到,那就好辦了,肯定是我新構建的REQUEST對象缺胳膊少腿了,搜索一通之后發現一篇大牛寫的文章:

Spring Cloud Gateway(讀取、修改 Request Body)

這里要再次表揚一下古哥,同樣是中文文章,度娘卻搜不到

不過文章中的spring cloud版本是

Spring Cloud: Greenwich.RC2

我本地是最新的Release版本RS3,并不能完全照搬過來,不過算是給了很大的啟發(如何獲取body以及重構)

下面給出我的代碼

網關中對body內容進行解密然后驗簽

/** * @author tengdj * @date 2019/8/13 11:08 * 設備接口驗簽,解密 **/@Slf4jpublic class TerminalSignFilter implements GatewayFilter, Ordered { private static final String AES_SECURTY = 'XXX'; private static final String MD5_SALT = 'XXX'; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { exchange.getAttributes().put('startTime', System.currentTimeMillis()); if (exchange.getRequest().getMethod().equals(HttpMethod.POST)) { //重新構造request,參考ModifyRequestBodyGatewayFilterFactory ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders()); MediaType mediaType = exchange.getRequest().getHeaders().getContentType(); //重點 Mono<String> modifiedBody = serverRequest.bodyToMono(String.class).flatMap(body -> { //因為約定了終端傳參的格式,所以只考慮json的情況,如果是表單傳參,請自行發揮 if (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || MediaType.APPLICATION_JSON_UTF8.isCompatibleWith(mediaType)) { JSONObject jsonObject = JSONUtil.toJO(body); String paramStr = jsonObject.getString('param'); String newBody; try{ newBody = verifySignature(paramStr); }catch (Exception e){ return processError(e.getMessage()); } return Mono.just(newBody); } return Mono.empty(); }); BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class); HttpHeaders headers = new HttpHeaders(); headers.putAll(exchange.getRequest().getHeaders()); //猜測這個就是之前報400錯誤的元兇,之前修改了body但是沒有重新寫content length headers.remove('Content-Length'); //MyCachedBodyOutputMessage 這個類完全就是CachedBodyOutputMessage,只不過CachedBodyOutputMessage不是公共的 MyCachedBodyOutputMessage outputMessage = new MyCachedBodyOutputMessage(exchange, headers); return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> { ServerHttpRequest decorator = this.decorate(exchange, headers, outputMessage); return returnMono(chain, exchange.mutate().request(decorator).build()); })); } else { //GET 驗簽 MultiValueMap<String, String> map = exchange.getRequest().getQueryParams(); if (!CollectionUtils.isEmpty(map)) { String paramStr = map.getFirst('param'); try{ verifySignature(paramStr); }catch (Exception e){ return processError(e.getMessage()); } } return returnMono(chain, exchange); } } @Override public int getOrder() { return 1; } private Mono<Void> returnMono(GatewayFilterChain chain,ServerWebExchange exchange){ return chain.filter(exchange).then(Mono.fromRunnable(()->{ Long startTime = exchange.getAttribute('startTime'); if (startTime != null){ long executeTime = (System.currentTimeMillis() - startTime); log.info('耗時:{}ms' , executeTime); log.info('狀態碼:{}' , Objects.requireNonNull(exchange.getResponse().getStatusCode()).value()); } })); } private String verifySignature(String paramStr) throws Exception{ log.info('密文{}', paramStr); String dParamStr; try{ dParamStr = AESUtil.decrypt(paramStr, AES_SECURTY); }catch (Exception e){ throw new Exception('解密失?。?); } log.info('解密得到字符串{}', dParamStr); String signature = SignUtil.sign(dParamStr, MD5_SALT); log.info('重新加密得到簽名{}', signature); JSONObject jsonObject1 = JSONUtil.toJO(dParamStr); if (!jsonObject1.getString('signature').equals(signature)) { throw new Exception('簽名不匹配!'); } return jsonObject1.toJSONString(); } private Mono processError(String message) { /*exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete();*/ log.error(message); return Mono.error(new Exception(message)); } ServerHttpRequestDecorator decorate(ServerWebExchange exchange, HttpHeaders headers, MyCachedBodyOutputMessage outputMessage) { return new ServerHttpRequestDecorator(exchange.getRequest()) { public HttpHeaders getHeaders() { long contentLength = headers.getContentLength(); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.putAll(super.getHeaders()); if (contentLength > 0L) { httpHeaders.setContentLength(contentLength); } else { httpHeaders.set('Transfer-Encoding', 'chunked'); } return httpHeaders; } public Flux<DataBuffer> getBody() { return outputMessage.getBody(); } }; }}

代碼到這里就結束了,希望看到的朋友可以少走點彎路,少踩點坑。

補充知識:springcloud gateway之addRequestParameter詳細使用及踩坑注意

SpringCloud的網關gateway提供了多個內置Filter,其中addRequestHeader是添加header的,這個無坑,比較簡單。還有一個添加參數的,addRequestParameter,這個就有點問題了。具體往下看。

版本如下,請注意Springboot版本,這是本篇Post請求異常的關鍵。

解決spring cloud gateway 獲取body內容并修改的問題

1 對應的uri只能是get請求

解決spring cloud gateway 獲取body內容并修改的問題

看一個簡單的示例,addRequestParameter,我們匹配/addParam請求,并將請求轉發至http://localhost:8888/header

這個是8888端口的服務

解決spring cloud gateway 獲取body內容并修改的問題

如果發起Get請求到網關,那么可以正常請求,一切OK。此時,調用發起方和最終的服務提供方都是Get請求,沒有問題。

如果發起的請求是Get,但是服務提供方是如下的Post。

解決spring cloud gateway 獲取body內容并修改的問題

注意,這里我用了PostMapping,然后分別啟動兩個工程,再訪問localhost:8080/addParam,而后會報錯,這個也可以理解。

解決spring cloud gateway 獲取body內容并修改的問題

但是,如果調用發起方和服務提供方都是Post請求,理論上應該也是OK的。

但是事實上不是的

解決spring cloud gateway 獲取body內容并修改的問題

網關程序會報錯如下:

解決spring cloud gateway 獲取body內容并修改的問題

這個就很尷尬了,作為一個網關,居然在代理非Get請求時出現異常,必然是不能容忍的。

經過一番探索,發現這是Springboot不同版本的原因導致,在Springboot2.0.5之前,不存在該問題,之后就有這種問題了。需要加以注意,解決方案會在下一篇寫。

2 添加的參數value值必須合法(不能含有空格)

解決spring cloud gateway 獲取body內容并修改的問題

上面已經知道了,addRequestParameter對應的后端請求是Get型,那么明顯添加的parameter只能是Get請求支持的,能在瀏覽器地址欄直接敲上去合法的。

這里,我將value的值變成帶空格的,然后去訪問后端的服務。

解決spring cloud gateway 獲取body內容并修改的問題

然后會發現控制臺報錯,Invalid URI query。這是因為get請求的value值不能含有非法字符.

解決spring cloud gateway 獲取body內容并修改的問題

同理

解決spring cloud gateway 獲取body內容并修改的問題

像這樣的,后臺接收的是

解決spring cloud gateway 獲取body內容并修改的問題

如果是這樣的參數

解決spring cloud gateway 獲取body內容并修改的問題

后臺這樣

解決spring cloud gateway 獲取body內容并修改的問題

結果是:

解決spring cloud gateway 獲取body內容并修改的問題

這樣就可以添加多個parameter了。

同時添加header和parameter

結束了addRequestParameter的說明,我們可以來看看,假如某個path,既想addHeader,又想addParameter,而系統的這兩個方法,都是一個path只能搭配一個add的filter,即便寫了兩個也不生效,如

解決spring cloud gateway 獲取body內容并修改的問題

解決spring cloud gateway 獲取body內容并修改的問題

結果就只有header被打印了

解決spring cloud gateway 獲取body內容并修改的問題

那么就是想同時添加header和parameter該怎么辦呢。

貌似通過java代碼是無法實現了,好在可以通過yml配置來實現。

spring: cloud: gateway: routes: - id: header uri: http://localhost:8888/header filters: - AddRequestHeader=NewHeader, Bar - AddRequestParameter=NewParam, Param predicates: - Path=/header

在yml就可以在filters里,添加多個filter了,注意不要寫錯了filter的名字。

可以看到結果

解決spring cloud gateway 獲取body內容并修改的問題

解決spring cloud gateway 獲取body內容并修改的問題

發現header和param都傳過來了。

以上這篇解決spring cloud gateway 獲取body內容并修改的問題就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持好吧啦網。

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
久久精品欧洲| 蜜臀av免费一区二区三区| 精品国产亚洲一区二区三区大结局| 欧美精品一卡| 青青青免费在线视频| 国产美女撒尿一区二区| 国产精品美女久久久| 成人日韩在线| 国产在线日韩精品| 国产亚洲人成a在线v网站| 视频一区视频二区在线观看| 欧美色图国产精品| 亚洲一级黄色| 91九色精品| 日本久久黄色| 国产精品久久久久av蜜臀| 日韩中文字幕在线一区| 国精品一区二区| 欧美一区二区三区高清视频| 亚洲精品88| 成人羞羞在线观看网站| 国产成人久久精品麻豆二区 | 精品国产乱码久久久| 久久只有精品| 中文在线资源| 国产va免费精品观看精品视频| 国产精品久久久网站| 国产亚洲精品v| 人人精品亚洲| 免费中文字幕日韩欧美| 99精品一区| 国户精品久久久久久久久久久不卡| 黄色成人91| 亚州欧美在线| 色乱码一区二区三区网站| 欧美 日韩 国产精品免费观看| 欧美中文日韩| 91p九色成人| 精品国产99| 亚洲女人av| 久久只有精品| 五月天av在线| 婷婷成人av| 欧美天堂视频| 日韩精品亚洲专区| 国产一区调教| 国产精品婷婷| 精品视频一区二区三区在线观看| 亚洲特级毛片| 久久一区国产| 亚洲欧美日本日韩| 精品国内亚洲2022精品成人| 亚洲激情社区| 日韩久久精品| 国产精品免费不| 蜜臀久久99精品久久久久久9| 日韩成人午夜精品| 久久久影院免费| 亚洲成av人片一区二区密柚| 精品午夜久久| 精品亚洲a∨| 亚洲人成网站在线在线观看| 国产91精品对白在线播放| 国产精品亚洲二区| 日韩高清在线一区| 亚洲三区欧美一区国产二区| 日韩一区精品视频| 蜜臀av一区二区在线免费观看| 欧美久久精品一级c片| 亚洲一级高清| 夜夜嗨网站十八久久| 成人一区不卡| 国产一区二区三区四区| 精品一区二区三区视频在线播放| 国产精品久久久久77777丨| 国产免费播放一区二区| 麻豆国产欧美日韩综合精品二区| 欧美交a欧美精品喷水| 电影91久久久| 99视频精品全国免费| 一区三区视频| 亚洲久久在线| 国产精品久久久久av蜜臀| 欧美精品第一区| 日韩在线欧美| 老色鬼久久亚洲一区二区| 日韩精品一区二区三区免费观影| 亚洲成a人片| 美女精品网站| 久久精品免费看| 五月天久久网站| 97精品资源在线观看| 久久久久97| 中文精品在线| 精品视频在线你懂得| 一区三区视频| 国产精品久久久网站| 日韩另类视频| 欧美日韩黄网站| 免费美女久久99| 精品在线91| 蜜臀久久久久久久| 久久精品国产一区二区| 夜夜嗨网站十八久久| 日韩av网站在线免费观看| 欧美好骚综合网| 日韩精品一区二区三区中文字幕| 国产精品久久久久久久免费观看| 久久xxxx| 亚洲a在线视频| 精品久久在线| 日韩一区二区三免费高清在线观看 | 午夜精品影视国产一区在线麻豆| 久久精品一区二区国产| 午夜在线一区| 欧美亚洲激情| 精品视频在线你懂得| 青草国产精品| 每日更新成人在线视频| 色综合www| 欧美aa一级| 久久久久久一区二区| 国产亚洲一区二区三区不卡| 亚洲影视一区| 亚洲精品电影| 精品一区二区三区免费看| 日本少妇精品亚洲第一区| 亚洲九九精品| 99国产成+人+综合+亚洲欧美| 国产66精品| 精品亚洲精品| 久久精品国产99国产| 国产精品地址| 亚洲精品在线二区| 综合激情网...| 一区二区三区午夜视频| 国产午夜精品一区二区三区欧美 | 国产亚洲亚洲| 麻豆精品91| 亚洲精品麻豆| 国产欧美自拍| 捆绑调教美女网站视频一区| 免费精品一区| 国产videos久久| 成人小电影网站| 日本在线高清| 精品一区三区| 日韩一区二区三区在线看| 欧美久久久网站| 日韩.com| av资源亚洲| 午夜宅男久久久| 国产麻豆一区| 日韩精品免费一区二区在线观看 | 日本中文字幕不卡| 麻豆精品久久久| 成人羞羞视频播放网站| 亚洲深夜影院| 国产日韩一区二区三区在线播放 | 日韩精品影视| 日韩欧美2区| 福利视频一区| 首页国产欧美日韩丝袜| 国产一区不卡| 亚久久调教视频| 亚洲美女久久精品| 日韩中文字幕视频网| 99国产精品免费视频观看| 亚洲一区二区三区免费在线观看 | 青草国产精品久久久久久| 中文字幕一区二区三区日韩精品| 婷婷五月色综合香五月| 精品一区二区男人吃奶| 伊人精品一区| 亚洲视频电影在线| 亚洲欧美日韩国产一区二区| 黄色在线一区| 你懂的亚洲视频| 欧美天堂一区| 久久久成人网| 国产aa精品| 亚洲tv在线| 久久亚洲在线| 日韩欧美午夜| 欧美偷窥清纯综合图区| 精品黄色一级片| 奇米狠狠一区二区三区| 欧美不卡高清一区二区三区| 日本不卡一二三区黄网| 亚洲精品黄色| 欧美99久久| 福利片在线一区二区| 亚洲我射av| 久久中文字幕av| 国产中文字幕一区二区三区| 黄色亚洲大片免费在线观看| 国内一区二区三区| 日韩精品一页| 免费看日韩精品| 999国产精品999久久久久久|