HTTPURL字符转义字符编码、RFC3986编码规范
⼀、为什么要编码转义
通常如果⼀样东西需要编码,说明这样东西并不适合传输。原因多种多样,如Size过⼤,包含隐私数据,对于Url来说,之所以要进⾏编码,是因为Url中有些字符会引起歧义。
例如Url参数字符串中使⽤key=value键值对这样的形式来传参,键值对之间以&符号分隔,如/s?q=abc&ie=utf-8。如果你的value字符串中包含了=或者&,那么势必会造成接收Url的服务器解析错误,因此必须将引起歧义的&和=符号进⾏转义,也就是对其进⾏编码。
⼜如,Url的编码格式采⽤的是ASCII码,⽽不是Unicode,这也就是说你不能在Url中包含任何⾮ASCII字符,例如中⽂。否则如果客户端浏览器和服务端浏览器⽀持的字符集不同的情况下,中⽂可能会造成问题。
Url编码的原则就是使⽤安全的字符(没有特殊⽤途或者特殊意义的可打印字符)去表⽰那些不安全的字符。
⼆、哪些字符需要编码
1、URL特殊字符转义,URL中⼀些字符的特殊含义,基本编码规则如下:
1、空格换成加号(+)
2、正斜杠(/)分隔⽬录和⼦⽬录
3、问号(?)分隔URL和查询
4、百分号(%)制定特殊字符
5、#号指定书签
6、&号分隔参数
2、不需要编码的字符:
RFC3986⽂档对Url的编解码问题做出了详细的建议,指出了哪些字符需要被编码才不会引起Url语义的转变,以及对为什么这些字符需要编码做出了相应的解释。
1、在US-ASCII字符集中没有的可打印字符:Url中只允许使⽤可打印字符。US-ASCII码中的10-7F字节全都表⽰控制字符,这些字符都不能直接出现在Url中。同时,对于80-FF字节(ISO-8859-1),由于已经超出了US-ACII定义的字节范围,因此也不可以放在Url中。
2、保留字符:Url可以划分成若⼲个组件,协议、主机、路径等。有⼀些字符(:/?#[]@)是⽤作分隔不同组件的。例如:冒号⽤于分隔协议和主机,/⽤于分隔主机和路径,?⽤于分隔路径和查询参数,等等。还有⼀些字符(!$&'()*+,;=)⽤于在每个组件中起到分隔作⽤的,如=⽤于表⽰查询参数中的键值对,&符号⽤于分隔查询多个键值对。当组件中的普通数据包含这些特殊字符时,需要对其进⾏编码。
RFC3986⽂档规定,Url中只允许包含以下四种:
1、英⽂字母(a-zA-Z)
2、数字(0-9)
3、-_.~ 4个特殊字符
4、所有保留字符,RFC3986中指定了以下字符为保留字符(英⽂字符): ! * ' ( ) ; : @ & = + $ , / ? # [ ]
3、需要编码的字符:
如果需要在URL中⽤到特殊字符,需要将这些特殊字符换成相应的⼗六进制的值
不安全字符:有⼀些字符,当他们直接放在Url中的时候,可能会引起解析程序的歧义。这些字符被视为不安全字符,原因有很多。
空格:Url在传输的过程,或者⽤户在排版的过程,或者⽂本处理程序在处理Url的过程,都有可能引⼊⽆关紧要的空格,或者将那些有意义的空格给去掉。
引号以及<>:引号和尖括号通常⽤于在普通⽂本中起到分隔Url的作⽤
#:通常⽤于表⽰书签或者锚点
%:百分号本⾝⽤作对不安全字符进⾏编码时使⽤的特殊字符,因此本⾝需要编码
{}|\^[]`~:某⼀些⽹关或者传输代理会篡改这些字符
需要注意的是,对于Url中的合法字符,编码和不编码是等价的,但是对于上⾯提到的这些字符,如果不经过编码,那么它们有可能会造成Url 语义的不同。因此对于Url⽽⾔,只有普通英⽂字符和数字,特殊字符$-_.+!*'()还有保留字符,才能出现在未经编码的Url之中。其他字符均需要经过编码之后才能出现在Url中。
但是由于历史原因,⽬前尚存在⼀些不标准的编码实现。例如对于~符号,虽然RFC3986⽂档规定,对于波浪符号~,不需要进⾏Url编码,但是还是有很多⽼的⽹关或者传输代理会。
三、如何对Url中的⾮法字符进⾏编码
Url编码通常也被称为百分号编码(Url Encoding,also known as percent-encoding),是因为它的编码⽅式⾮常简单,使⽤%百分号加上两位的字符——0123456789ABCDEF——代表⼀个字节的⼗六进制形式。Url编码默认使⽤的字符集是US-ASCII。例如a在US-ASCII码中对应的字节是0x61,那么Url编码之后得到的就是%61,我们在地址栏上输⼊g/search?q=%61%62%63,实际上就等同于在google上搜索abc 了。⼜如@符号在ASCII字符集中对应的字节为0x40,经过Url编码之后得到的是%40。
对于⾮ASCII字符,需要使⽤ASCII字符集的超集进⾏编码得到相应的字节,然后对每个字节执⾏百分号编码。对于Unicode字符,RFC⽂档建议使⽤utf-8对其进⾏编码得到相应的字节,然后对每个字节执⾏百分号编码。如"中⽂"使⽤UTF-8字符集得到的字节为0xE4 0xB8 0xAD 0xE6 0x96 0x87,经过Url编码之后得到"%E4%B8%AD%E6%96%87"。
如果某个字节对应着ASCII字符集中的某个⾮保留字符,则此字节⽆需使⽤百分号表⽰。例如"Url编码",使⽤UTF-8编码得到的字节是0x55
0x72 0x6C 0xE7 0xBC 0x96 0xE7 0xA0 0x81,由于前三个字节对应着ASCII中的⾮保留字符"Url",因此这三个字节可以⽤⾮保留字符"Url"表⽰。最终的Url编码可以简化成"Url%E7%BC%96%E7%A0%81
" ,当然,如果你⽤"%55%72%6C%E7%BC%96%E7%A0%81"也是可以的。列举带有特殊字符的参数替换成另⼀些代替的参数,如下所⽰
字符 - URL编码值
空格 - %20 (URL中的空格可以⽤+号或者编码值表⽰)
" - %22
# - %23
% - %25
& - %26
( - %28
) - %29
+ - %2B
, - %2C
/ - %2F
: - %3A
; - %3B
< - %3C
= - %3D
> - %3E
- %3F
@ - %40
\ - %5C
| - %7C
{ - %7B
} - %7D
四、具体编码处理⽅法
⽤URLEncode先对你原始url做个编码,然后使⽤编码后的String。
encodeURIComponent(JSON.stringify(files)) 加⼀下encodeURIComponen 处理即可。
web端:Javascript的escape(),encodeURIComponent(),encodeURI ()这三个函数进⾏URL编码,防⽌特殊字符接收不到。
Java代码:
五、案例
在将tomcat升级到7.0.81版后,发现系统的有些功能不能使⽤了,查询⽇志发现是有些地址直接被tomcat认为存在不合法字符,返回HTTP 400错误响应,错⼊信息如下:
1、原因分析
经了解,这个问题是⾼版本tomcat中的新特性:就是严格按照 RFC 3986规范进⾏访问解析,⽽ RFC 3986规范定义了Url中只允许包含英⽂字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符(RFC3986中指定了以下字符为保留字符:! * ’ ( ) ; : @ & = + $ , / ? # [ ])。⽽我们的系统在通过地址传参时,在url中传了⼀段json,传⼊的参数中有"{"不在RFC3986中的保留字段中,所以会报这个错。
根据(/bugzilla/i?id=60594),从以下版本开始,有配置项能够关闭/配置这个⾏为:
8.5.x系列的:8.5.12 onwards
8.0.x系列的:8.0.42 onwards
7.0.x系列的:7.0.76 onwards
2、处理⽅法
.../conf/catalina.properties中,到最后注释掉的⼀⾏#tomcat.util.http.questTargetAllow=| ,改成
tomcat.util.http.questTargetAllow=|{},表⽰把{}放⾏
在线url网址编码解码Ps:当然也可以在参数传递前对URL先编码。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论