原文链接: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中文参数乱码

  1. URL编码问题&乱码根源
  2. IE6-IE11 Get请求参数带中文tomcat 返回400错误并显示:Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
  3. where to define ALLOW_UNESCAPED_CHARACTERS_IN_URL property to allow characters like {|}`^\><#" in URLs

IE浏览器中文参数导致400 Bad Request问题研究(转)相关推荐

  1. IE浏览器url带中文参数导致乱码问题(chrome下正常)

    问题: E浏览器下url带中文请求参数,服务器端使用new String(param.getBytes("iso-8859-1"), "utf-8")后仍然会乱 ...

  2. ie浏览器地址栏中文参数提交服务器乱码分析

    今天我遇到了一个奇怪的问题.之前我通过360浏览器地址栏输入中文参数提交到服务器,服务器解析正常.如下所示: 但是在偶然的情况下,我直接启动了myeclipse自带的浏览器,结果就发现了问题: 所以我 ...

  3. 使用UC浏览器安卓版访问大多数网站遇到400 bad request错误

    Hoxily在使用Android版本的UC浏览器访问许多网站时出现400 Bad Request错误. 有一些好心的网站在给出400错误提示的同时,还指出了 Invalid Header. 错误原因: ...

  4. 前台拼接中文参数乱码提交400报错后台无响应

    问题描述:JSP中使用ajax get方式提交表单数据请求,使用英文参数浏览器正常拼接和调用后台接口,输入中文参数拼接乱码,显示400报错,后台打断点无响应. 解决思路:网友提示说将参数使用encod ...

  5. 使用C语言通过POST通信,空格导致的400 Bad Request

    1.直接上组合之前的格式: #define HTTP_POST "POST /%s HTTP/1.1\r\nHOST: %s:%d\r\nAccept: */*\r\n"\&quo ...

  6. 火狐浏览器访问网站出现 HTTP Error 400. The request is badly formed.错误,怎么解决

    今天在访问某个网站时,出现一个"HTTP Error 400. The request is badly formed."错误, 那么应该如何解决呢? 1.问题描述: 用火狐浏览网 ...

  7. 400 (Bad Request)错误的解决方法

    把get改为post就好了???? 原因1:没有转义字符,特殊符号String类型不能接收 原因2:浏览器对传的参数长度有限制 我们在访问接口时的URL是有长度限制的!!! 浏览器: IE浏览器对UR ...

  8. liunx 上get 不到url参数 java_URL传递中文参数,大坑一枚,Windows与Linux效果竟然不一致...

    下午,计划2个小时搞定,个人官网第6次升级,就可以干点轻松的事了,结果,下午多搞了2个小时,晚上又搞了2个小时,才搞定.最后一个世界难题是,URL传递中文参数.问题大致是这么出现的:我为"博 ...

  9. java中文 x_java环境url中文参数乱码处理

    在做搜索开发过程中,由于翻页功能需要,要把当前查询的中文条件放在URL中带到服务器进行下一页查询,结果出现乱码情况. 此时情况有如下两种: 1.在输入框输入搜索内容,直接通过from提交,参数值正常读 ...

最新文章

  1. 2021年大数据Hadoop(二十五):YARN通俗介绍和基本架构
  2. 【状态保持】Cache 基于SQL 数据库 的缓存依赖 轮询机制详解
  3. canvas学习笔记(下篇) -- canvas入门教程--保存状态/变形/旋转/缩放/矩阵变换/综合案例(星空/时钟/小球)...
  4. 川大优秀毕业生在GitHub上建了一个项目《深度学习500问》,还未完结就获赞无数
  5. realARM s5pv210开发板wifi开机启动设置方法 开机启动linux应用程序
  6. Linux 命令(51)—— ipcs 命令
  7. VS2010测试方面的文章
  8. 第4章 更新Erlang.mk
  9. Hololens开发学习笔记——海康摄像头直播视频流
  10. C语言时间片轮转调度算法
  11. 虚拟机安装linux系统教程
  12. PHP爬虫常用技术:v8js(执行js代码)
  13. word图片撑满,word怎么让图片占满整个页面?
  14. word中将英文及数字全部修改为Times New Roman字体
  15. python培训时间多长
  16. 剑指spring源码(三)
  17. 电子商务项目设计(案例)
  18. JETSON产品组合: nano, TX, Xavier
  19. NTC电阻抑制冷机启动浪涌电流
  20. iOS开发之Unity游戏在iOS平台运行调研(踩坑)

热门文章

  1. unicloud生成微信小程序分享码
  2. Nginx安装部署与配置管理
  3. linux程序设计第三版 金国庆,浙江大学Linux程序设计教学大纲与建议学时分配数-金国庆刘加海...
  4. elastic如何和mysql同步数据_MySQL数据库之mysql 同步数据到 ElasticSearch 的方案
  5. Python数据分析【第9天】| DataFrame的属性编码、数据合并和连接(get_dummies,merge,join,concat)
  6. 使用Date得到时间差
  7. 博客园离线写博客工具
  8. Winphone Hyper-V模拟器设置
  9. Google 镜像站大集合
  10. C++生成 桔灯 Aether仪器的 *.atts 格式 时间域文件