微服务模式下url中带{}[]等特殊字符时请求异常返回400

问题描述:
前后端分离项目,前端使用查询时参数中带有[]{}等特殊字符时,前端直接返回400异常问题。

单体模式下get请求带有路径参数,这个参数中有[]或者/这个特殊字符,前端已经转移成了%2F,后端用的是springboot,并没有收到这个请求,直接返回了400的错误。(注意是后端根本没有收到请求就直接报400了);

这个问题是由于Tomcat的新版本中增加了一个新特性,就是严格按照 RFC 3986规范进行访问解析,而 RFC 3986规范定义了Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符(RFC3986中指定了以下字符为保留字符:! * ’ ( ) ; : @ & = + $ , / ? # [ ])。

单体模式解决办法:
①将get请求换成post请求;
②前端处理请求时URL encode处理特殊字段
③重写tomcat的TomcatConnectorCustomizer类

@Configuration
public class Config {
  @Bean
  public TomcatServletWebServerFactory webServerFactory() {
     TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
     factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
	     @Override
	     public void customize(Connector connector) {
	         connector.setProperty("relaxedPathChars", "\"<>[\\]^`{|}");
	         connector.setProperty("relaxedQueryChars", "\"<>[\\]^`{|}");
	         connector.setProperty("rejectIllegalHeader", "false");
	      }
      });
      return factory;
  }
}

微服务模式下的处理方式:
①将get请求换成post请求;
②在gateway服务下实现WebServerFactoryCustomizer接口

/**
 * @Author MrYang
 * @Description 解决通过网关调用服务时,url中含有 [] {}等字符时浏览器400异常
 * @Version 1.0
 */
@Component
@Slf4j
public class EncodeQueryNettyWebServerCustomizer
        implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory> {

    /**
     * 需要encode的特殊字符
     */
    private final List<Character> charList = new ArrayList<Character>() {
        {
            this.add('{');
            this.add('}');
            this.add('[');
            this.add(']');
        }
    };

    @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) throws UnsupportedEncodingException {
            if (msg instanceof HttpRequest) {
                HttpRequest request = (HttpRequest) msg;
                String url = request.uri();
                // fix url
                String[] split = url.split("\\?");
                StringBuilder fixUrl = new StringBuilder(split[0]);
                if (split.length > 1) {
                    fixUrl.append("?");
                    char[] chars = split[1].toCharArray();
                    for (char aChar : chars) {
                        if (charList.contains(aChar)) {
                            fixUrl.append(URLEncoder.encode(String.valueOf(aChar), "UTF-8"));
                        }else {
                            fixUrl.append(aChar);
                        }
                    }
                }
                request.setUri(fixUrl.toString());
            }
            ctx.fireChannelRead(msg);
        }
    }
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值