博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
异常:Invalid character found in the request target. The valid characters are defined in RFC 3986
阅读量:2142 次
发布时间:2019-04-30

本文共 3872 字,大约阅读时间需要 12 分钟。

一、背景

  事情是这样的,前几天做一个基本的数据库“增删改查”的需求,前端传参的方式是“JSON字符串”,后端接收到此参数后,使用阿里巴巴fastjson进行解析,然后入库。需求很简单吧,但是偏偏遇到问题了。

  我发现,JSON字符串里面无数组,纯粹的都是json结构的时候,即都是“{}”时,不会报错,传参入库没问题。但是只要传参的值里面有数组,即有“[]”的结构时,就报错。报错内容如下(我的tomcat版本是8.5.45):

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)    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:684)    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:800)    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1471)    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)    at java.lang.Thread.run(Thread.java:748)

二、原因

  tomcat的原因。 tomcat严格按照RFC规范进行范文解析,随着网络环境的变化,RFC规范也在不断的修改和升级中,发布了好多版本。而tomcat的不同版本中,采用的RFC规范的版本是不同的。所以你会在下文发现,有的低版本tomcat没有这个问题。

  tomcat自tomcat 8.0.35版本之后对URL参数做了比较规范的限制,必须遵循RFC 7230 and RFC 3986规范,对于非保留字字符(json格式的请求参数)必须做转义操作。例如:RFC 3986规范定义了Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符(RFC3986中指定了以下字符为保留字符:! * ’ ( ) ; : @ & = + $ , / ? # [ ])。

  Request For Comments(RFC),是一系列以编号排定的文件。文件收集了有关互联网相关信息,以及UNIX和互联网社区的软件文件。目前RFC文件是由Internet Society(ISOC)赞助发行。基本的互联网通信协议都有在RFC文件内详细说明。RFC文件还额外加入许多在标准内的论题,例如对于互联网新开发的协议及发展中所有的记录。因此几乎所有的互联网标准都有收录在RFC文件之中——百度百科。

  附上网络大牛的源码分析:

分析的是org.apache.tomcat.util.http.parser.HttpParser//tomcat 8.2.3 版本及 tomcat 7.0.82 ,都有如下代码,读取配置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)));        }    }}而tomcat 8.0.14 版本中并没有读取配置,对 | { } 的处理,而是默认为合法字符。static {    for (int i = 0; i < 128; i++) {        if (i < 32) {            isToken[i] = false;        } else if (i == ‘(‘ || i == ‘)‘ || i == ‘<‘ || i == ‘>‘  || i == ‘@‘  ||                   i == ‘,‘ || i == ‘;‘ || i == ‘:‘ || i == ‘\\‘ || i == ‘\"‘ ||                   i == ‘/‘ || i == ‘[‘ || i == ‘]‘ || i == ‘?‘  || i == ‘=‘  ||                   i == ‘{‘ || i == ‘}‘ || i == ‘ ‘ || i == ‘\t‘) {            isToken[i] = false;        } else {            isToken[i] = true;        }        if (i >= ‘0‘ && i <= ‘9‘ || i >= ‘A‘ && i <= ‘F‘ ||i >= ‘a‘ && i <= ‘f‘) {            isHex[i] = true;        } else {            isHex[i] = false;        }    }}可以看出在 8.0.x 左右的一些版本中,tomcat.util.http.parser.HttpParser. requestTargetAllow (下文方法三)这个配置是没有生效的,即| { } 这3个符号认为是合法的。

三、解决

  注:我是使用“方法五”解决问题的,推荐“方法五”。

  方法一:换到低版本的Tomcat。

  方法二:在Catalina.properties中添加tomcat.util.http.parser.HttpParser.requestTargetAllow=|{}这个东西明显是允许“|”和大括号的,但是我现在的问题是中括号。

  方法三:添加tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true这个是允许url中带有特殊字符的。试过了,也不好使。

  方法四:对传递的“JSON字符串”进行url编码后在传递,可以规避这个方括号。前端用“encodeURI(xxx)”方法编码,后端用“URLDecoder.decode(xxx, "utf-8")”解码即可。

  方法五:在tomcat目录的conf文件夹下,server.xml的Connector中添加了这个relaxedQueryChars="[,]"。

      注:

1、如果还有其他特殊的字符串,也可以直接添加到这个属性里;

2、如果你是springboot项目,可以在SpringBootApplication的的main方法中增加:System.setProperty("tomcat.util.http.parser.HttpParser.requestTargetAllow","[]");       

技术分享图片

参考

1、https://blog.csdn.net/Hitler698/article/details/85720156

2、https://my.oschina.net/pding/blog/1794176

3、http://www.bubuko.com/infodetail-3238579.html

你可能感兴趣的文章
【LEETCODE】88-Merge Sorted Array
查看>>
【LEETCODE】19-Remove Nth Node From End of List
查看>>
【LEETCODE】125-Valid Palindrome
查看>>
【LEETCODE】28-Implement strStr()
查看>>
【LEETCODE】6-ZigZag Conversion
查看>>
【LEETCODE】8-String to Integer (atoi)
查看>>
【LEETCODE】14-Longest Common Prefix
查看>>
【LEETCODE】38-Count and Say
查看>>
【LEETCODE】278-First Bad Version
查看>>
【LEETCODE】303-Range Sum Query - Immutable
查看>>
【LEETCODE】21-Merge Two Sorted Lists
查看>>
【LEETCODE】231-Power of Two
查看>>
【LEETCODE】172-Factorial Trailing Zeroes
查看>>
【LEETCODE】112-Path Sum
查看>>
【LEETCODE】9-Palindrome Number
查看>>
【极客学院】-python学习笔记-Python快速入门(面向对象-引入外部文件-Web2Py创建网站)
查看>>
【LEETCODE】190-Reverse Bits
查看>>
【LEETCODE】67-Add Binary
查看>>
【LEETCODE】7-Reverse Integer
查看>>
【LEETCODE】165-Compare Version Numbers
查看>>