电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

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

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

瀏覽:45日期: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
相關文章:
主站蜘蛛池模板: 隧道风机_DWEX边墙风机_SDS射流风机-绍兴市上虞科瑞风机有限公司 | 挤奶设备过滤纸,牛奶过滤纸,挤奶机过滤袋-济南蓝贝尔工贸有限公司 | 原子吸收设备-国产分光光度计-光谱分光光度计-上海光谱仪器有限公司 | 胶水,胶粘剂,AB胶,环氧胶,UV胶水,高温胶,快干胶,密封胶,结构胶,电子胶,厌氧胶,高温胶水,电子胶水-东莞聚力-聚厉胶粘 | 自动钻孔机-全自动数控钻孔机生产厂家-多米(广东)智能装备有限公司 | 环氧树脂地坪漆_济宁市新天地漆业有限公司 | 老城街小面官网_正宗重庆小面加盟技术培训_特色面馆加盟|牛肉拉面|招商加盟代理费用多少钱 | 工业硝酸钠,硝酸钠厂家-淄博「文海工贸」 | 北京乾茂兴业科技发展有限公司 | 影合社-影视人的内容合作平台| 扒渣机,铁水扒渣机,钢水扒渣机,铁水捞渣机,钢水捞渣机-烟台盛利达工程技术有限公司 | 杭州翻译公司_驾照翻译_专业人工翻译-杭州以琳翻译有限公司官网 组织研磨机-高通量组织研磨仪-实验室多样品组织研磨机-东方天净 | 煤棒机_增碳剂颗粒机_活性炭颗粒机_木炭粉成型机-巩义市老城振华机械厂 | 通用磨耗试验机-QUV耐候试验机|久宏实业百科| 福州时代广告制作装饰有限公司-福州广告公司广告牌制作,福州展厅文化墙广告设计, | 北京易通慧公司从事北京网站优化,北京网络推广、网站建设一站式服务商-北京网站优化公司 | DNA亲子鉴定_DNA基因检测中心官方预约平台-严选好基因网 | 蒸压釜_蒸养釜_蒸压釜厂家-山东鑫泰鑫智能装备有限公司 | 铝板冲孔网,不锈钢冲孔网,圆孔冲孔网板,鳄鱼嘴-鱼眼防滑板,盾构走道板-江拓数控冲孔网厂-河北江拓丝网有限公司 | 礼仪庆典公司,礼仪策划公司,庆典公司,演出公司,演艺公司,年会酒会,生日寿宴,动工仪式,开工仪式,奠基典礼,商务会议,竣工落成,乔迁揭牌,签约启动-东莞市开门红文化传媒有限公司 | 扬尘在线监测系统_工地噪声扬尘检测仪_扬尘监测系统_贝塔射线扬尘监测设备「风途物联网科技」 | 中央空调温控器_风机盘管温控器_智能_液晶_三速开关面板-中央空调温控器厂家 | 成都租车_成都租车公司_成都租车网_众行宝 | 便携式谷丙转氨酶检测仪|华图生物科技百科 | 高温链条油|高温润滑脂|轴承润滑脂|机器人保养用油|干膜润滑剂-东莞卓越化学 | 保镖公司-私人保镖-深圳保镖公司【环宇兄弟保镖】 | 写方案网_方案策划方案模板下载 事迹材料_个人事迹名人励志故事 | 定制异形重型钢格栅板/钢格板_定做踏步板/排水沟盖板_钢格栅板批发厂家-河北圣墨金属制品有限公司 | 二次元影像仪|二次元测量仪|拉力机|全自动影像测量仪厂家_苏州牧象仪器 | TPM咨询,精益生产管理,5S,6S现场管理培训_华谋咨询公司 | 航空障碍灯_高中低光强航空障碍灯_民航许可认证航空警示灯厂家-东莞市天翔航天科技有限公司 | SDI车窗夹力测试仪-KEMKRAFT方向盘测试仪-上海爱泽工业设备有限公司 | 理化生实验室设备,吊装实验室设备,顶装实验室设备,实验室成套设备厂家,校园功能室设备,智慧书法教室方案 - 东莞市惠森教学设备有限公司 | 锂电叉车,电动叉车_厂家-山东博峻智能科技有限公司 | 东莞喷砂机-喷砂机-喷砂机配件-喷砂器材-喷砂加工-东莞市协帆喷砂机械设备有限公司 | 康明斯发电机,上柴柴油发电机,玉柴柴油发电机组_海南重康电力官网 | 阳光模拟试验箱_高低温试验箱_高低温冲击试验箱_快速温变试验箱|东莞市赛思检测设备有限公司 | 新型游乐设备,360大摆锤游乐设备「诚信厂家」-山东方鑫游乐设备 新能源汽车电池软连接,铜铝复合膜柔性连接,电力母排-容发智能科技(无锡)有限公司 | 扒渣机厂家_扒渣机价格_矿用扒渣机_铣挖机_撬毛台车_襄阳永力通扒渣机公司 | 小型气象站_便携式自动气象站_校园气象站-竞道气象设备网 | 澳门精准正版免费大全,2025新澳门全年免费,新澳天天开奖免费资料大全最新,新澳2025今晚开奖资料,新澳马今天最快最新图库-首页-东莞市傲马网络科技有限公司 |