首页 > 解决方案 > Zuul 网关异常中的 java.net.URI 编码异常

问题描述

Spring-boot-2.1.4.RELEASE 正在运行一个 Zuul 应用程序。

当我要求http://192.168.10.84:8080/app/rest/micro1/inquiry/printCarInquiryList/1?param={%22storeHouseId%22:%22%22,%22storeHouseName%22:%22%22,%22storeHouseType%22:%22%22,%22plaqueSeries%22:%22%22,%22productionYearFrom%22:%22-1%22,%22productionYearTo%22:%22-1%22,%22overallInquery%22:false,%22edited%22:false,%22confirmerCount%22:%22-1%22,%22reportStoreHouseType%22:%22-1%22,%22plaqueNumber%22:%22%22,%22motorNumber%22:%22%22,%22motorNumberOperator%22:%227%22,%22chassisNumber%22:%22%22,%22chassisNumberOperator%22:%227%22,%22storeHouseShowType%22:%221%22,%22havePlaque%22:%22-1%22,%22isFilterByStoreHouseStatus%22:true,%22storeHouseList%22:[%221518691%22],%22goodsStatus%22:null,%22statusId%22:%22-1%22,%22goodsDeleted%22:null,%22formType%22:1,%22searchFilter%22:%22%22,%22order%22:%22%20e.samapelItem.id%20%22,%22pageNumber%22:0,%22pageSize%22:%227%22,%22plaqueType%22:%22-1%22}

引发以下异常:

引起:java.net.URISyntaxException:索引 95 处查询中的非法字符:http: //192.168.10.84 :8080/app/rest/micro1/inquiry/printCarInquiryList/1?param={%id%22:%22%22,%22storeHouseName%22:%22%22,%22storeHouseType%22:%22%22,%22plaqueSeries%22:%22%22,%22productionYearFrom%22:%22-1 %22,%22productionYearTo%22:%22-1%22,%22overallInquery%22:false,%22edited%22:false,%22confirmerCount%22:%22-1%22,%22reportStoreHouseType%22:%22-1 %22,%22plaqueNumber%22:%22%22,%22motorNumber%22:%22%22,%22motorNumberOperator%22:%227%22,%22chassisNumber%22:%22%22,%22chassisNumberOperator%22:%227 %22,%22storeHouseShowType%22:%221%22,%22havePlaque%22:%22-1%22,%22isFilterByStoreHouseStatus%22:true,%22storeHouseList%22:[%221518691%22],%22goodsStatus%22:null ,%22statusId%22:%22-1%22,%22goodsDeleted%22:null,%22formType%22:1,%22searchFilter%22:%22%22,%22order%22:%22%20e.samapelItem.id %20%22,%22pageNumber%22:0,%22pageSize%22:%227%22,%22plaqueType%22:%22-1%22} 在 java.net.URI$Parser.fail(URI.java:2848 ) ~[na:1.8.0_181] 在 java.net。URI$Parser.checkChars(URI.java:3021) ~[na:1.8.0_181] at java.net.URI$Parser.parseHierarchical(URI.java:3111) ~[na:1.8.0_181] at java.net。 URI$Parser.parse(URI.java:3053) ~[na:1.8.0_181] at java.net.URI.(URI.java:588) ~[na:1.8.0_181] at java.net.URI.create (URI.java:850) ~[na:1.8.0_181]

而有以下配置:

@Bean
    public ConfigurableServletWebServerFactory webServerFactory() {
        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
        factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
            @Override
            public void customize(Connector connector) {
                connector.setProperty("relaxedQueryChars", "|{}[]");
            }
        });
        return factory;
    }

哪里错了?

标签: javaspring-boottomcatnetflix-zuul

解决方案


解决这个问题的标准方法是解码一些敏感的字符,比如{等等,但是当有一个应用程序有接近 1000 个 JSP 文件没有编码这些字符时,这种方式要么是不可能的,要么是困难的适用于使用这些字符的所有点。因此,问题是ZUUL Filter这样解决的:

@Component
public class CharacterEncodingZuulFilter extends ZuulFilter {


    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 10000;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();

        Map<String, String[]> qp = new HashMap<>();
        String s = "";
        try {
            s = ctx.getRequest().getQueryString().replaceAll("\\{", URLEncoder.encode("{", "UTF-8"));
            s = s.replaceAll("}", URLEncoder.encode("}", "UTF-8"));
            s = s.replaceAll("\\[", URLEncoder.encode("[", "UTF-8"));
            s = s.replaceAll("]", URLEncoder.encode("]", "UTF-8"));

            HttpServletRequest request = ctx.getRequest();

            CustomRequestWrapper wrapped = new CustomRequestWrapper(request, qp, s);

            ctx.setRequest(wrapped);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return null;
    }
}

推荐阅读