SpringBoot内嵌tomcat处理有特殊字符转义的问题
作者:苏暮沉觞
SpringBoot内嵌tomcat处理有特殊字符转义
前段时间在发生了前端调后台接口失败,原因是url中存在特殊字符,SpringBoot自带的tomcat无法正常解析,返回400 bad Request。
网上搜了一下,发现是因为tomcat高版本中,更加严格按照 RFC 3986规范进行访问解析,而 RFC 3986规范规定Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符(RFC3986中指定了以下字符为保留字符:! * ’ ( ) ; : @ & = + $ , / ? # [ ])。。
在这里记录一下解决过程。
SpringBoot版本为 2.2.5release(不同版本的解决方式可能不同)。
实际解决方式(针对于使用SpringBoot内置的Tomcat)
添加下面的配置Bean。
/** * 配置转义字符,解决当请求路径中特殊字符,高版本tomcat解析失败的问题 */ @Bean public ServletWebServerFactory webServerFactory() { TomcatServletWebServerFactory fa = new TomcatServletWebServerFactory(); fa.addConnectorCustomizers(connector -> { connector.setProperty("relaxedQueryChars", "(),/:;<=>?@[\\]{}"); connector.setProperty("rejectIllegalHeader", "false"); }); return fa; }
(该内容只是用于记录,具体是否有效没有测试过)如果你不是使用SpringBoot的tomcat启动项目,那你就需要在tomcat的配置文件中添加以下配置信息,并重新启动。
org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
Springboot2中修改tomcat参数支持请求特殊符号
解决:java.lang.IllegalArgumentException: Invalid character found in ...
使用Springboot2中内置的tomcat启动项目时候,前端发来的请求报错:
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:488) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:260) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.33.jar:9.0.33]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-9.0.33.jar:9.0.33]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1594) [tomcat-embed-core-9.0.33.jar:9.0.33]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.33.jar:9.0.33]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_144]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_144]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.33.jar:9.0.33]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_144]
这段报错的意思是:请求中含有无效字符,有效的字符在RFC 7230和RFC 3986中定义
出现这个错误的原因是:我们在前后台交互的时候请求的参数,其中含有“{}”“[]”这些特殊符号,在高版本的tomcat中含有这些字符的请求会被拦截。
例如:http://localhost:8080/sendMail?content=[1007]...
解决方法
springboot项目中增加一个配置,将webServerFactory方法加入到springboot启动类中,配置文件代码如下:
import org.apache.catalina.connector.Connector; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class TomcatConfig { @Bean public TomcatServletWebServerFactory webServerFactory() { TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(); factory.addConnectorCustomizers((Connector connector) -> { connector.setProperty("relaxedPathChars", "\"<>[\\]^`{|}"); connector.setProperty("relaxedQueryChars", "\"<>[\\]^`{|}"); }); return factory; } }
这样就解决问题啦!
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。