写点什么

Spring Cloud Gateway 和 Webflux 请求参数非法字符处理

用户头像
a1vin-tian
关注
发布于: 2021 年 04 月 21 日

背景

业务接入一些投放,投放请求回调时候会调用我们的服务器,其中经过了 gateway。回调过来的时候,业务反映请求没有打到业务服务器,而是返回了 HTTP CODE 400,去 gateway 也没有任何异常,请求的链接类似于http://localhost:8080/test-like-this?a={{bbb}},于是开始排查。

原因

首先确认是 gateway 拦截的,因为层级没有到应用端,中间也没有任何链路了。

然后调试 java 代码进行复现,追着调用栈找到了在下列地方被拦截了,抛了java.net.URISyntaxException: Illegal character in query异常,拦截原因是 url 有非法字符,其中{}就是不按照 http 标准规范的非法字符。



经过分析,发现spring-freamwork使用的ServerHttpRequest做为请求的包装类,这个对象使用了java.lang.URI这个对象作为暴漏和操作 Url 的主要手段。内部实现和解析query都是使用的URI这个对象。URI创建的时候会效验传入的 url 是否合法,如果不合法的话就会抛异常。




spring-reactive整个链路都是使用ServerHttpRequest封装的请求,上面也可以看到,大概有 102 处引用(有一些注释很少)。所以说就只能接受合法参数了,除非你把代码上下游所有用到 URI 的地方都改了才行,这是难的,而且产出也不大,所以说无法透传原请求到后端了,webflux 底层也用的ServerHttpRequest所以说是一样的。

解决方案

使用 Webflux 的项目和 spring-cloud-gateway 的项目,在 GET 请求的时候不能加非法字符,如果想处理带有非法字符的请求,只能服务端将非法字符转义,暂时没有其他方案。


类似问题.


spring 开了口子,可以实现WebServerFactoryCustomizer在请求进来的时候先把请求的query encode

public class EncodeQueryNettyWebServerCustomizer        implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory> {
@Override public void customize(NettyReactiveWebServerFactory factory) { factory.addServerCustomizers(httpServer -> httpServer.observe((conn, state) -> { if (state == ConnectionObserver.State.CONNECTED) { conn.channel().pipeline().addAfter(NettyPipeline.HttpCodec, "", new QueryHandler()); } })); }

class QueryHandler extends ChannelInboundHandlerAdapter {
public QueryHandler() { }
@Override public void channelRead(ChannelHandlerContext ctx, Object msg) { if (msg instanceof HttpRequest) { HttpRequest request = (HttpRequest) msg; String url = request.uri(); // todo fix url request.setUri(fixUrl); } ctx.fireChannelRead(msg); } }}
复制代码


发布于: 2021 年 04 月 21 日阅读数: 109
用户头像

a1vin-tian

关注

还未添加个人签名 2018.04.21 加入

还未添加个人简介

评论

发布
暂无评论
Spring Cloud Gateway 和Webflux 请求参数非法字符处理