本次代码仅在以下版本中测试通过
123456789101112131415161718 <dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Greenwich.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId><version>2.1.4.RELEASE</version></dependency>
这几天在用gateway进行鉴权校验的时候遇到很多坑,以前使用的都是x-www-form-urlencoded这种格式的Body,很容易就可以用gateway打开进行操作,但这次因为涉及到图片上传,所以请求格式变了,打开的过程变得非常曲折。
先是找到了下面这种办法,确实可以打开并获取body里的内容,而且还是非常规则的类型,不需要二次提取,formData即是我们想要的内容,后来在路由之后的controller中发现body里没有数据了,原来gateway只能打开一次。
|
1 2 3 4 5 6 7 8 9 |
MediaType mediaType = exchange.getRequest().getHeaders().getContentType(); if (MediaType.MULTIPART_FORM_DATA.isCompatibleWith(mediaType)) { return exchange.getMultipartData().flatMap(formData->{ exchange.getAttributes().put(GateWayFilterDict.FORM_DATA_ATTR,formData); return chain.filter(exchange.mutate().build()); }); } |
后来换成了这个样子,先使用GlobalFilter对body内容进行缓存,之后便可以在方法里进行调用
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
@Component public class CacheBodyGlobalFilter implements Ordered, GlobalFilter { public static final String CACHE_REQUEST_BODY_OBJECT_KEY = "cachedRequestBodyObject"; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { if (exchange.getRequest().getHeaders().getContentType() == null) { return chain.filter(exchange); } else { return DataBufferUtils.join(exchange.getRequest().getBody()) .flatMap(dataBuffer -> { DataBufferUtils.retain(dataBuffer); Flux<DataBuffer> cachedFlux = Flux .defer(() -> Flux.just(dataBuffer.slice(0, dataBuffer.readableByteCount()))); ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator( exchange.getRequest()) { @Override public Flux<DataBuffer> getBody() { return cachedFlux; } }; exchange.getAttributes().put(CACHE_REQUEST_BODY_OBJECT_KEY, cachedFlux); return chain.filter(exchange.mutate().request(mutatedRequest).build()); }); } } @Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; } } |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
<br />public class VerificationFilter implements GatewayFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String bodyContent = resolveBodyFromRequest(exchange.getRequest()); return chain.filter(exchange); } public static String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest){ //获取请求体 Flux<DataBuffer> body = serverHttpRequest.getBody(); StringBuilder sb = new StringBuilder(); body.subscribe(buffer -> { byte[] bytes = new byte[buffer.readableByteCount()]; buffer.read(bytes); // DataBufferUtils.release(buffer); String bodyString = new String(bytes, StandardCharsets.UTF_8); sb.append(bodyString); }); return formatStr(sb.toString()); } /** * 去掉空格,换行和制表符 * @param str * @return */ private static String formatStr(String str){ if (str != null && str.length() > 0) { Pattern p = Pattern.compile("\\s*|\t|\r|\n"); Matcher m = p.matcher(str); return m.replaceAll(""); } return str; } @Override public int getOrder() { return 1; } } |
这里是提取出来的内容,需要根据规则进行二次加工,但不复杂
|
1 2 3 4 |
----------------------------582918735041218588371746Content-Disposition:form-data;name="appKey"4324----------------------------582918735041218588371746Content-Disposition:form-data;name="appSecret"43244----------------------------582918735041218588371746-- |