IE浏览器中文参数导致400 Bad Request问题研究(转)
原文链接:https://www.jianshu.com/p/3816bb5ce3c9
问题描述
本人在使用Jboss-eap-7.1(内核是Wildfly)时,向服务器发送带中文url参数的Get请求时,服务器会返回400错误。而且应用根本接收不到该请求的信息,在连接层面就被拦截了,没有将请求转给应用处理。不止是Wildfly,tomcat的7,8版本也存在一样的情况。
问题探究
经过实验,发现IE浏览器6, 8, 11版本均存在该问题,但chrome浏览器正常,微软的Edge浏览器也是正常的。除了中文,如果参数含有'<', '{'等特殊字符时,IE浏览器也会报400错误。经过查找资料和抓包分析,发现是编码问题导致了两个浏览器的结果不同,但不是大家一般认为的字符集的原因。下面是不同浏览器针对GET请求URL编码情况的分析。对于GET URL http://example.com/test?lover=樊
- chrome浏览器先使用UTF-8字符集编码URL中的所有字符,再使用 %编码(Percent-Encoding)将字节转换为%HH(%+两个十六进制数字)的形式,这样可以保证URL中全部是标准ASCII字符。樊的UTF-8编码为{E6, A8, 8A},实际发送的请求是 http://example.com/test?lover=%E6%A8%8A
- IE浏览器会使用GBK字符集编码URL中的参数,但不会转换为%编码。樊的GBK编码为{B7, AE} 。实际发送的请求时,直接将樊字对应的GBK字节作为请求的内容。
以上分析也许不太容易理解,我们再从字节的角度详细解释一下。
下面是chrome浏览器发送请求的抓包内容,尾部的参数是=%E6%A8%8A,实际发送的字节为{ 3D, 25, 45, 36, 25, 41, 38, 25, 38, 41, 38, 41 }。'=' 的ASCII码为3D,'%' 的ASCII码为25,'E' 的ASCII码为45,以此类推。
下面是IE浏览器发送请求的抓包内容,尾部的参数是=樊,实际发送的字节为{ 3D, B7, AE }。B7和AE都是超出RFC 3986规范允许的字节。
%编码是使用字符集编码后,再将每个超出规范允许范围的字节转换为 %+字节对应的十六进制 的形式。
另外,IE中有一个选项,“发送UTF-8 URL”。选中之后,参数还是以GBK格式发送。这个仅仅对URL路径中的字符生效,选中就是UTF-8,不勾选就是GBK。但对于URL参数没有作用,永远都使用GBK字符集。IE会对路径中的字符做%编码,URL参数不做。
根本原因
所以问题的根本原因是IE没有遵循RFC 3986规范,未对URL参数使用 %编码,而是直接将字符对应的字节码发送到服务器。Wildfly服务器端的安全机制对此类URL做了拦截。它在该版本做了更新,遵循RFC 3986规范,对于url中含有非法字符的请求,直接予以拒绝,并返回400错误。相关代码摘录如下:
private static final boolean[] ALLOWED_TARGET_CHARACTER = new boolean[256];
………… ………… …………
for(int i = 0; i < 256; ++i) {if(i < 32 || i > 126) {ALLOWED_TARGET_CHARACTER[i] = false;} else {switch ((char)i) {case '\"':case '#':case '<':case '>':case '\\':case '^':case '`':case '{':case '|':case '}':ALLOWED_TARGET_CHARACTER[i] = false;break;default:ALLOWED_TARGET_CHARACTER[i] = true;}}
}
………… ………… …………
while (buffer.hasRemaining()) {char next = (char) (buffer.get() & 0xFF);if(!allowUnescapedCharactersInUrl && !ALLOWED_TARGET_CHARACTER[next]) {throw new BadRequestException(UndertowMessages.MESSAGES.invalidCharacterInRequestTarget(next));}
………… ………… …………
}
可以看出,对于ASCII码在32-125之外的字符,是不允许的,直接抛出异常。对于该范围内的字符,有10个不允许出现。
根据代码,可以解释上述中文的问题。由GBK编码规范可知,字符的第一个字节肯定大于127,不被服务器接受,所以返回了400错误。
所以,问题并不是字符集导致的,而是%编码导致的。即使使用GBK编码中文字符,只要将字符的每个字节都转换为%HH的形式,依然能正确发送请求。至于可能导致的乱码问题,也有解决方式。但最好根据规范使用UTF-8。
根据参考资料2显示,Tomcat7,8也严格执行了RFC 3986规范,阻止不安全字符。但我认为该文章对原因的分析是不准确的。
Jboss下解决方案
根据UNDERTOW-1185的ISSUE,Undertow在该版本做了更新,增加了一个开关选项 ALLOW_UNESCAPED_CHARACTERS_IN_URL ,当配置为true时,就不再根据规范限制url中的字符。相应地,Jboss eap根据JBEAP-13710的ISSUE,将在JBEAP-13744更新Undertow版本,预计会在Jboss-eap-7.1.1版本中见到新的配置项。
但如果有条件,最好还是使用encodeUrl()
编码一下,可以避免很多问题。与之相关的资料非常多,本文不再赘述。
参考资料
4. URL中文参数乱码
- URL编码问题&乱码根源
- IE6-IE11 Get请求参数带中文tomcat 返回400错误并显示:Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
- where to define ALLOW_UNESCAPED_CHARACTERS_IN_URL property to allow characters like {|}`^\><#" in URLs
IE浏览器中文参数导致400 Bad Request问题研究(转)相关推荐
- IE浏览器url带中文参数导致乱码问题(chrome下正常)
问题: E浏览器下url带中文请求参数,服务器端使用new String(param.getBytes("iso-8859-1"), "utf-8")后仍然会乱 ...
- ie浏览器地址栏中文参数提交服务器乱码分析
今天我遇到了一个奇怪的问题.之前我通过360浏览器地址栏输入中文参数提交到服务器,服务器解析正常.如下所示: 但是在偶然的情况下,我直接启动了myeclipse自带的浏览器,结果就发现了问题: 所以我 ...
- 使用UC浏览器安卓版访问大多数网站遇到400 bad request错误
Hoxily在使用Android版本的UC浏览器访问许多网站时出现400 Bad Request错误. 有一些好心的网站在给出400错误提示的同时,还指出了 Invalid Header. 错误原因: ...
- 前台拼接中文参数乱码提交400报错后台无响应
问题描述:JSP中使用ajax get方式提交表单数据请求,使用英文参数浏览器正常拼接和调用后台接口,输入中文参数拼接乱码,显示400报错,后台打断点无响应. 解决思路:网友提示说将参数使用encod ...
- 使用C语言通过POST通信,空格导致的400 Bad Request
1.直接上组合之前的格式: #define HTTP_POST "POST /%s HTTP/1.1\r\nHOST: %s:%d\r\nAccept: */*\r\n"\&quo ...
- 火狐浏览器访问网站出现 HTTP Error 400. The request is badly formed.错误,怎么解决
今天在访问某个网站时,出现一个"HTTP Error 400. The request is badly formed."错误, 那么应该如何解决呢? 1.问题描述: 用火狐浏览网 ...
- 400 (Bad Request)错误的解决方法
把get改为post就好了???? 原因1:没有转义字符,特殊符号String类型不能接收 原因2:浏览器对传的参数长度有限制 我们在访问接口时的URL是有长度限制的!!! 浏览器: IE浏览器对UR ...
- liunx 上get 不到url参数 java_URL传递中文参数,大坑一枚,Windows与Linux效果竟然不一致...
下午,计划2个小时搞定,个人官网第6次升级,就可以干点轻松的事了,结果,下午多搞了2个小时,晚上又搞了2个小时,才搞定.最后一个世界难题是,URL传递中文参数.问题大致是这么出现的:我为"博 ...
- java中文 x_java环境url中文参数乱码处理
在做搜索开发过程中,由于翻页功能需要,要把当前查询的中文条件放在URL中带到服务器进行下一页查询,结果出现乱码情况. 此时情况有如下两种: 1.在输入框输入搜索内容,直接通过from提交,参数值正常读 ...
最新文章
- 2021年大数据Hadoop(二十五):YARN通俗介绍和基本架构
- 【状态保持】Cache 基于SQL 数据库 的缓存依赖 轮询机制详解
- canvas学习笔记(下篇) -- canvas入门教程--保存状态/变形/旋转/缩放/矩阵变换/综合案例(星空/时钟/小球)...
- 川大优秀毕业生在GitHub上建了一个项目《深度学习500问》,还未完结就获赞无数
- realARM s5pv210开发板wifi开机启动设置方法 开机启动linux应用程序
- Linux 命令(51)—— ipcs 命令
- VS2010测试方面的文章
- 第4章 更新Erlang.mk
- Hololens开发学习笔记——海康摄像头直播视频流
- C语言时间片轮转调度算法
- 虚拟机安装linux系统教程
- PHP爬虫常用技术:v8js(执行js代码)
- word图片撑满,word怎么让图片占满整个页面?
- word中将英文及数字全部修改为Times New Roman字体
- python培训时间多长
- 剑指spring源码(三)
- 电子商务项目设计(案例)
- JETSON产品组合: nano, TX, Xavier
- NTC电阻抑制冷机启动浪涌电流
- iOS开发之Unity游戏在iOS平台运行调研(踩坑)
热门文章
- unicloud生成微信小程序分享码
- Nginx安装部署与配置管理
- linux程序设计第三版 金国庆,浙江大学Linux程序设计教学大纲与建议学时分配数-金国庆刘加海...
- elastic如何和mysql同步数据_MySQL数据库之mysql 同步数据到 ElasticSearch 的方案
- Python数据分析【第9天】| DataFrame的属性编码、数据合并和连接(get_dummies,merge,join,concat)
- 使用Date得到时间差
- 博客园离线写博客工具
- Winphone Hyper-V模拟器设置
- Google 镜像站大集合
- C++生成 桔灯 Aether仪器的 *.atts 格式 时间域文件