最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解決springboot URL帶有斜杠的轉(zhuǎn)義字符百分之2F導(dǎo)致的400錯(cuò)誤

 更新時(shí)間:2021年08月30日 09:22:28   作者:ColdFireMan  
這篇文章主要介紹了解決springboot URL帶有斜杠的轉(zhuǎn)義字符百分之2F導(dǎo)致的400錯(cuò)誤問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

springboot URL帶有斜杠的轉(zhuǎn)義字符百分之2F導(dǎo)致的400錯(cuò)誤

今天項(xiàng)目上出現(xiàn)一個(gè)問題,是前端的GET請求url中帶有路徑參數(shù),這個(gè)參數(shù)中有/這個(gè)特殊字符,前端已經(jīng)轉(zhuǎn)移成了%2F,后端用的是springboot,并沒有收到這個(gè)請求,直接返回了400的錯(cuò)誤

原因

據(jù)說是tomcat默認(rèn)是不支持轉(zhuǎn)義的,需要手動(dòng)設(shè)置一下轉(zhuǎn)化,這個(gè)搜索tomcat的設(shè)置可以找到,但是這個(gè)是springboot,有內(nèi)置的tomcat,但是在yml中找不到相關(guān)的配置。

解決方式

修改一下啟動(dòng)類,加一個(gè)系統(tǒng)參數(shù),重寫WebMvcConfigurerAdapter的configurePathMatch方法

@SpringBootApplication
public class Application extends WebMvcConfigurerAdapter {
    public static void main(String[] args) throws Exception {
        System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
        SpringApplication.run(Application.class, args);
    }
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        urlPathHelper.setUrlDecode(false);
        configurer.setUrlPathHelper(urlPathHelper);
    }
}

springboot 1.x 2.x tomcat支持特殊字符

URL中有{}[]等報(bào)400

現(xiàn)象

正常訪問一個(gè)get請求,頁面返回400: 在這里插入圖片描述

后臺日志報(bào)錯(cuò):

2018-08-09 21:39:28.915  INFO 6750 --- [nio-8080-exec-1] o.apache.coyote.http11.Http11Processor   : Error parsing HTTP request header
 Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.
java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
    at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:479) ~[tomcat-embed-core-8.5.32.jar:8.5.32]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:684) ~[tomcat-embed-core-8.5.32.jar:8.5.32]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.32.jar:8.5.32]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:800) [tomcat-embed-core-8.5.32.jar:8.5.32]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1471) [tomcat-embed-core-8.5.32.jar:8.5.32]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.32.jar:8.5.32]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_111]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_111]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.32.jar:8.5.32]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_111]

稍微百度一下就可以知道這是URL中有特殊字符,新版本的Tomcat嚴(yán)格按照RFC 3986規(guī)范進(jìn)行訪問解析,而 RFC 3986規(guī)范規(guī)定Url中只允許包含英文字母(a-zA-Z)、數(shù)字(0-9)、-_.~4個(gè)特殊字符以及所有保留字符(RFC3986/7320中指定了以下字符為保留字符:! * ' ( ) ; : @ & = + $ , / ? # [ ]) 。

3.2.6. Field Value Components Most HTTP header field values are defined using common syntax components (token, quoted-string, and comment) separated by whitespace or specific delimiting characters. Delimiters are chosen from the set of US-ASCII visual characters not allowed in a token (DQUOTE and “(),/:;<=>?@[]{}”).

所以這個(gè)問題特別容易出現(xiàn)在升級spring boot版本的時(shí)候,spring boot內(nèi)嵌的tomcat也會升級,老版的tomcat運(yùn)行正常,新版的tomcat就會出錯(cuò)。而深究特殊字符來源,一般是get請求中包含json字符串、搜索特殊字符關(guān)鍵字等。

解決方案

如果是在開發(fā)新業(yè)務(wù)過程中出現(xiàn)這個(gè)問題,可以選擇新的方案,避免在GET請求中使用! * ' ( ) ; : @ & = + $ , / ? # [ ])等字符,畢竟符合規(guī)范是最好的出路。

如果是升級,可以使用下面的方式來解決:

sprintboot 1.x(1.5.21測試有效)

import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * Create by IntelliJ IDEA
 *
 * @author chenlei
 * @dateTime 2019/5/23 18:09
 * @description TomcatConfig
 */
@Configuration
public class TomcatConfig {
    @Bean
    public EmbeddedServletContainerCustomizer containerCustomizer() {
        return new MyCustomizer();
    }
    private static class MyCustomizer implements EmbeddedServletContainerCustomizer {
        @Override
        public void customize(ConfigurableEmbeddedServletContainer factory) {
            if (factory instanceof TomcatEmbeddedServletContainerFactory) {
                customizeTomcat((TomcatEmbeddedServletContainerFactory) factory);
            }
        }
        void customizeTomcat(TomcatEmbeddedServletContainerFactory factory) {
            factory.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> {
                connector.setAttribute("relaxedPathChars", "<>[\\]^`{|}");
                connector.setAttribute("relaxedQueryChars", "<>[\\]^`{|}");
            });
        }
    }
}

springboot 2.x(2.1.3測試有效)

import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * Create by IntelliJ IDEA
 *
 * @author chenlei
 * @dateTime 2019/5/23 18:09
 * @description TomcatConfig
 */
@Configuration
public class TomcatConfig {
    @Bean
    public ServletWebServerFactory webServerFactory() {
        TomcatServletWebServerFactory fa = new TomcatServletWebServerFactory();
        fa.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> connector.setProperty("relaxedQueryChars", "[]{}"));
        return fa;
    }
}

總結(jié)

這次問題出現(xiàn)的原因是升級springboot導(dǎo)致的,因?yàn)橹笆褂玫妮^低版本的springboot(1.5.10.RELEASE),升級到1.5.21.RELEASE后出現(xiàn)了該問題。因?yàn)橹霸趕pringboot 2.x上遇到過這個(gè)問題,因此知道問題所在,但springboot 1.x和2.x的解決方案有一點(diǎn)差異,這里記錄一下。

后續(xù)

后面再做了一次Tomcat升級,從9.0.21升級到9.0.31,突然又出現(xiàn)這個(gè)問題,問題原因是一樣的,tomcat對非法字符的控制更加嚴(yán)格了,嚴(yán)格遵循最新的RFC7230,我們除了把所有的非法字符全部加到relaxedQueryChars以外,還添加了另一項(xiàng)配置rejectIllegalHeader:

@Configuration
public class TomcatConfig {
    @Bean
    public ServletWebServerFactory webServerFactory() {
        TomcatServletWebServerFactory fa = new TomcatServletWebServerFactory();
        fa.addConnectorCustomizers(connector -> {
            connector.setProperty("relaxedQueryChars", "(),/:;<=>?@[\\]{}");
            connector.setProperty("rejectIllegalHeader", "false");
        });
        return fa;
    }
}

關(guān)于這個(gè)配置的解釋參考:tomcat-9.0-doc

rejectIllegalHeader

If an HTTP request is received that contains an illegal header name or value (e.g. the header name is not a token) this setting determines if the request will be rejected with a 400 response (true) or if the illegal header be ignored (false). The default value is true which will cause the request to be rejected.

這樣配置后(1.x的配置類似),大部分URI和Header都可以兼容,但是正如文檔里所說的,rejectIllegalHeader會導(dǎo)致非法的header忽略,即header信息將不會被服務(wù)器接收。

所以一旦Header里面有非法字符,對應(yīng)的Header項(xiàng)將被忽略,服務(wù)器不會報(bào)400,但會跳過這個(gè)header項(xiàng),比如升級過程中我們發(fā)現(xiàn)有API在header里傳輸中文,導(dǎo)致服務(wù)啟報(bào)錯(cuò),加了rejectIllegalHeader=false后,不報(bào)400,但程序找不到對應(yīng)的Header,最后不得不刪除這些不規(guī)范的header。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家.

相關(guān)文章

  • 詳解Spring中bean的幾種注入方式

    詳解Spring中bean的幾種注入方式

    這篇文章主要介紹了詳解Spring中bean的幾種注入方式,主要介紹了4種注入,主要有屬性注入、構(gòu)造函數(shù)注入、工廠方法注入,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-06-06
  • 將應(yīng)用程序進(jìn)行Spring6遷移的最佳使用方式

    將應(yīng)用程序進(jìn)行Spring6遷移的最佳使用方式

    這篇文章主要介紹了將應(yīng)用程序進(jìn)行Spring6遷移的最佳方式,以及如何充分利用此升級,需要的朋友可以參考下,如有錯(cuò)誤的地方還請指正
    2023-03-03
  • Java實(shí)現(xiàn)字符串解析為日期時(shí)間的方法示例

    Java實(shí)現(xiàn)字符串解析為日期時(shí)間的方法示例

    這篇文章主要介紹了Java實(shí)現(xiàn)字符串解析為日期時(shí)間的方法,結(jié)合具體實(shí)例形式分析了java日期時(shí)間字符串的解析操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-04-04
  • Java 如何實(shí)現(xiàn)AES加密

    Java 如何實(shí)現(xiàn)AES加密

    這篇文章主要介紹了Java 如何實(shí)現(xiàn)AES加密,幫助大家完成對接,完成自身需求,感興趣的朋友可以了解下
    2020-10-10
  • java實(shí)現(xiàn)登錄窗口

    java實(shí)現(xiàn)登錄窗口

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)登錄窗口,含驗(yàn)證碼驗(yàn)證、賬戶注冊等,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • 詳解spring cloud如何使用spring-test進(jìn)行單元測試

    詳解spring cloud如何使用spring-test進(jìn)行單元測試

    這篇文章主要介紹了spring cloud如何使用spring-test進(jìn)行單元測試,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • Mybatis choose when用法實(shí)例代碼

    Mybatis choose when用法實(shí)例代碼

    本文通過實(shí)例代碼給大家介紹了Mybatis choose when用法,需要的的朋友參考下吧
    2017-06-06
  • Java二叉樹路徑和代碼示例

    Java二叉樹路徑和代碼示例

    這篇文章主要介紹了Java二叉樹路徑和代碼示例,具有一定借鑒價(jià)值,需要的朋友可以參考下。
    2017-12-12
  • SpringBoot自動(dòng)配置的8個(gè)技巧分享

    SpringBoot自動(dòng)配置的8個(gè)技巧分享

    在 SpringBoot 2.x中,一個(gè)很核心的功能是自動(dòng)配置機(jī)制,這篇文章主要為大家詳細(xì)介紹了Spring Boot 2.x 實(shí)現(xiàn)自動(dòng)配置的8個(gè)技巧,希望對大家有所幫助
    2025-01-01
  • Java中的值傳遞以及引用傳遞和數(shù)組傳遞詳解

    Java中的值傳遞以及引用傳遞和數(shù)組傳遞詳解

    這篇文章主要介紹了Java中的值傳遞以及引用傳遞和數(shù)組傳遞詳解,Java不允許程序員選擇按值傳遞還是按引用傳遞各個(gè)參數(shù),就對象而言,不是將對象本身傳遞給方法,而是將對象的的引用或者說對象的首地址傳遞給方法,引用本身是按值傳遞的,需要的朋友可以參考下
    2023-07-07

最新評論

兰坪| 涟水县| 楚雄市| 肃南| 东莞市| 新沂市| 蒙自县| 河间市| 琼海市| 遵义县| 青铜峡市| 新化县| 华坪县| 淳安县| 县级市| 永嘉县| 乌拉特中旗| 皋兰县| 永靖县| 绥德县| 夏河县| 玛沁县| 永定县| 龙泉市| 佳木斯市| 萝北县| 巴林左旗| 克拉玛依市| 神农架林区| 宁阳县| 务川| 临沧市| 绥滨县| 涪陵区| 保康县| 涞源县| 伊金霍洛旗| 五原县| 林州市| 仁化县| 乃东县|