springboot两个版1.5.8和1.5.22在路径包含大括号区别

1.5.8得使用下面属性 启动参数中增加以下配置

tomcat.util.http.parser.HttpParser.requestTargetAllow

如:

-Dtomcat.util.http.parser.HttpParser.requestTargetAllow={}|

源码如下

    static {
        String prop = System.getProperty("tomcat.util.http.parser.HttpParser.requestTargetAllow");
        if (prop != null) {
            for (int i = 0; i < prop.length(); i++) {
                char c = prop.charAt(i);
                if (c == '{' || c == '}' || c == '|') {
                    REQUEST_TARGET_ALLOW[c] = true;
                } else {
                    log.warn(sm.getString("httpparser.invalidRequestTargetCharacter",
                            Character.valueOf(c)));
                }
            }
        }

        for (int i = 0; i < ARRAY_SIZE; i++) {
            // Control> 0-31, 127
            if (i < 32 || i == 127) {
                IS_CONTROL[i] = true;
            }

            // Separator
            if (    i == '(' || i == ')' || i == '<' || i == '>'  || i == '@'  ||
                    i == ',' || i == ';' || i == ':' || i == '\\' || i == '\"' ||
                    i == '/' || i == '[' || i == ']' || i == '?'  || i == '='  ||
                    i == '{' || i == '}' || i == ' ' || i == '\t') {
                IS_SEPARATOR[i] = true;
            }

            // Token: Anything 0-127 that is not a control and not a separator
            if (!IS_CONTROL[i] && !IS_SEPARATOR[i] && i < 128) {
                IS_TOKEN[i] = true;
            }

            // Hex: 0-9, a-f, A-F
            if ((i >= '0' && i <='9') || (i >= 'a' && i <= 'f') || (i >= 'A' && i <= 'F')) {
                IS_HEX[i] = true;
            }

            // Not valid for request target.
            // Combination of multiple rules from RFC7230 and RFC 3986. Must be
            // ASCII, no controls plus a few additional characters excluded
            if (IS_CONTROL[i] || i > 127 ||
                    i == ' ' || i == '\"' || i == '#' || i == '<' || i == '>' || i == '\\' ||
                    i == '^' || i == '`'  || i == '{' || i == '|' || i == '}') {
                if (!REQUEST_TARGET_ALLOW[i]) {
                    IS_NOT_REQUEST_TARGET[i] = true;
                }
            }

            // Not valid for HTTP protocol
            // "HTTP/" DIGIT "." DIGIT
            if (i == 'H' || i == 'T' || i == 'P' || i == '/' || i == '.' || (i >= '0' && i <= '9')) {
                IS_HTTP_PROTOCOL[i] = true;
            }
        }
    }

其中改属性配置的时候只有{}|三个字符有效,REQUEST_TARGET_ALLOW将该数组设置成true,IS_NOT_REQUEST_TARGET正好相反 使用时如下

    public static boolean isNotRequestTarget(int c) {
        // Fast for valid request target characters, slower for some incorrect
        // ones
        try {
            return IS_NOT_REQUEST_TARGET[c];
        } catch (ArrayIndexOutOfBoundsException ex) {
            return true;
        }
    }
                if (chr == Constants.SP || chr == Constants.HT) {
                    space = true;
                    end = pos;
                } else if (chr == Constants.CR || chr == Constants.LF) {
                    // HTTP/0.9 style request
                    parsingRequestLineEol = true;
                    space = true;
                    end = pos;
                } else if (chr == Constants.QUESTION && parsingRequestLineQPos == -1) {
                    parsingRequestLineQPos = pos;
                } else if (HttpParser.isNotRequestTarget(chr)) {
                    throw new IllegalArgumentException(sm.getString("iib.invalidRequestTarget"));
                }

如果解析器返回的是不允许的字符HttpParser.isNotRequestTarget(chr)则报错误

java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986

1.5.22版本采用另一种方法

    @Bean
    public EmbeddedServletContainerFactory webServerFactory() {
        TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
        factory.addConnectorCustomizers((connector) ->
                connector.setProperty("relaxedQueryChars", "[]{}")
        );

        return factory;
    }

查看httpParser方式

    public HttpParser(String relaxedPathChars, String relaxedQueryChars) {
        for(int i = 0; i < 128; ++i) {
            if ((IS_CONTROL[i] || i > 127 || i == 32 || i == 34 || i == 35 || i == 60 || i == 62 || i == 92 || i == 94 || i == 96 || i == 123 || i == 124 || i == 125) && !REQUEST_TARGET_ALLOW[i]) {
                this.IS_NOT_REQUEST_TARGET[i] = true;
            }

            if (IS_USERINFO[i] || i == 64 || i == 47 || REQUEST_TARGET_ALLOW[i]) {
                this.IS_ABSOLUTEPATH_RELAXED[i] = true;
            }

            if (this.IS_ABSOLUTEPATH_RELAXED[i] || i == 63 || REQUEST_TARGET_ALLOW[i]) {
                this.IS_QUERY_RELAXED[i] = true;
            }
        }

        this.relax(this.IS_ABSOLUTEPATH_RELAXED, relaxedPathChars);
        this.relax(this.IS_QUERY_RELAXED, relaxedQueryChars);
    }
    

增加构造,接纳两个参数,relaxedPathChars,relaxedQueryChars 同时也支持

        String prop = System.getProperty("tomcat.util.http.parser.HttpParser.requestTargetAllow");
        if (prop != null) {
            for(int i = 0; i < prop.length(); ++i) {
                char c = prop.charAt(i);
                if (c != '{' && c != '}' && c != '|') {
                    log.warn(sm.getString("http.invalidRequestTargetCharacter", new Object[]{c}));
                } else {
                    REQUEST_TARGET_ALLOW[c] = true;
                }
            }
        }

使用时改位以下内容

 byte chr = this.byteBuffer.get();
                                if (chr != 32 && chr != 9) {
                                    if (chr != 13 && chr != 10) {
                                        if (chr == 63 && this.parsingRequestLineQPos == -1) {
                                            this.parsingRequestLineQPos = pos;
                                        } else {
                                            if (this.parsingRequestLineQPos != -1 && !this.httpParser.isQueryRelaxed(chr)) {
                                                this.request.protocol().setString("HTTP/1.1");
                                                throw new IllegalArgumentException(sm.getString("iib.invalidRequestTarget"));
                                            }

                                            if (this.httpParser.isNotRequestTargetRelaxed(chr)) {
                                                this.request.protocol().setString("HTTP/1.1");
                                                throw new IllegalArgumentException(sm.getString("iib.invalidRequestTarget"));
                                            }
                                        }
                                    } else {
    public boolean isQueryRelaxed(int c) {
        try {
            return this.IS_QUERY_RELAXED[c];
        } catch (ArrayIndexOutOfBoundsException var3) {
            return false;
        }
    }

看的是这个数组IS_QUERY_RELAXED

在构造的时候

public Http11Processor(int maxHttpHeaderSize, boolean allowHostHeaderMismatch, boolean rejectIllegalHeaderName, AbstractEndpoint<?> endpoint, int maxTrailerSize, Set<String> allowedTrailerHeaders, int maxExtensionSize, int maxSwallowSize, Map<String, UpgradeProtocol> httpUpgradeProtocols, boolean sendReasonPhrase, String relaxedPathChars, String relaxedQueryChars) {
        super(endpoint);
        this.httpParser = new HttpParser(relaxedPathChars, relaxedQueryChars);
        this.inputBuffer = new Http11InputBuffer(this.request, maxHttpHeaderSize, rejectIllegalHeaderName, this.httpParser);
        this.request.setInputBuffer(this.inputBuffer);
        this.outputBuffer = new Http11OutputBuffer(this.response, maxHttpHeaderSize, sendReasonPhrase);
        this.response.setOutputBuffer(this.outputBuffer);
        this.inputBuffer.addFilter(new IdentityInputFilter(maxSwallowSize));
        this.outputBuffer.addFilter(new IdentityOutputFilter());
        this.inputBuffer.addFilter(new ChunkedInputFilter(maxTrailerSize, allowedTrailerHeaders, maxExtensionSize, maxSwallowSize));
        this.outputBuffer.addFilter(new ChunkedOutputFilter());
        this.inputBuffer.addFilter(new VoidInputFilter());
        this.outputBuffer.addFilter(new VoidOutputFilter());
        this.inputBuffer.addFilter(new BufferedInputFilter());
        this.outputBuffer.addFilter(new GzipOutputFilter());
        this.pluggableFilterIndex = this.inputBuffer.getFilters().length;
        this.httpUpgradeProtocols = httpUpgradeProtocols;
        this.allowHostHeaderMismatch = allowHostHeaderMismatch;
    }

会将两个参数传入 修改IS_QUERY_RELAXED数组的值,1.5.22两种都可以

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值