springcloudgateway全局过滤器获取body体内容

来源:10-10 全局过滤器

锅锅_java

2020-11-21

springcloudgateway里面全局过滤器无法获取body内容,如下图所示,控制台先打印出来body.subscribe方法下面的代码,业务需要是先要获取body.subscribe里面body的内容,求助,谢谢
图片描述

写回答

2回答

大目

2020-11-22

我写了一个,可以参考下:

@Component
public class TokenCheckRequestGlobalLogFilter implements GlobalFilter, Ordered {
    public static final Logger log = LoggerFactory.getLogger(TokenCheckRequestGlobalLogFilter.class);
    private GatewayFilter delegate;
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取请求对象
        ServerHttpRequest request = exchange.getRequest();
        // 只读取 contentType 为 application/json 的数据
        MediaType contentType = request.getHeaders().getContentType();
        if (MediaType.APPLICATION_JSON.equals(contentType) || MediaType.APPLICATION_JSON_UTF8.equals(contentType)) {
            return delegate.filter(exchange, chain);
        }
        // 获取GET请求参数信息
        else if (HttpMethod.GET == request.getMethod()) {
            log.info("get请求的request param = {}", request.getQueryParams().toSingleValueMap());
            // 正常放行的处理,进入下一个过滤链
            return chain.filter(exchange);
        }
        // 其他请求直接放行
        return chain.filter(exchange);
    }
    @PostConstruct
    public void init() {
        this.delegate = new ModifyRequestBodyGatewayFilterFactory().apply(this.getConfig());
    }
    private ModifyRequestBodyGatewayFilterFactory.Config getConfig() {
        ModifyRequestBodyGatewayFilterFactory.Config cf = new ModifyRequestBodyGatewayFilterFactory.Config();
        cf.setRewriteFunction(Object.class, Object.class, getRewriteFunction());
        return cf;
    }
    private RewriteFunction<Object, Object> getRewriteFunction() {
        return (serverWebExchange, body) -> {
            // 这里的 body 就是请求体参数, 类型是 LinkedHashMap, 可以根据需要转成JSON
            LinkedHashMap bodyMap = (LinkedHashMap) body;
            // 我取的消息体中的"token"属性,你按照你的情况取下
            String token = bodyMap.get("token").toString();
            log.info("request body = {}, token = {}", body, token);
            // 校验token,如果token不合法:
            if (!"some-token".equals(token)) {
                // 直接抛异常,然后用spring cloud gateway的统一异常管理
                throw new IllegalArgumentException("xxx");
            }
            return Mono.just(body);
        };
    }
    @Override
    public int getOrder() {
        return 0;
    }
}


异常处理参考下这里吧: https://www.cnblogs.com/yinjihuan/p/10474774.html


PS. 建议最好还是把签名什么的放到header里面去,处理起来简单很多。

1
5
大目
回复
锅锅_java
什么是统一返回不行?
2020-11-24
共5条回复

大目

2020-11-22

您好,目测您是想修改http请求,修改http请求不能这样玩哈。

subscribe() 只会接收到第一个发出的元素,所以会导致获取不全的问题(太长的 Body 会被截断)

-----

要想修改http请求的话,建议用ModifyRequestBodyGatewayFilterFactory,同理,如果想修改响应,建议用ModifyResponseBodyGatewayFilterFactory。

用法可参考: https://www.imooc.com/article/290816   24-25节

官方文档: https://github.com/spring-cloud/spring-cloud-gateway/blob/master/docs/src/main/asciidoc/spring-cloud-gateway.adoc#modify-a-request-body-gatewayfilter-factory


-----

如果你就是想自己写,不想用内置的过滤器,可以参考下这篇文章:https://winrains.cn/archives/7733

实际上,这个里面的代码也是参考ModifyRequestBodyGatewayFilterFactory写的。

0
1
锅锅_java
不是修改http请求,是要获取body内容进行验签,签名过了,再让进入请求的服务
2020-11-22
共1条回复

Spring Cloud Alibaba微服务从入门到进阶

面向未来微服务:熟练掌握Spring Cloud Alibaba

3085 学习 · 1324 问题

查看课程