设为首页 收藏本站
查看: 538|回复: 0

[经验分享] Tomcat处理编码的流程

[复制链接]

尚未签到

发表于 2017-1-21 09:47:16 | 显示全部楼层 |阅读模式
  Tomcat是如何处理query/post的编码问题的?
首先我们看看get方式时,tomcat如何获取querystring。
比如我们的url是:http://abc.com/?keywords=%C6%A1%BE%C6    (其中%C6%A1%BE%C6是啤酒的GBK的URLEncode编码)
当请求来到服务器的tomcat(也可以说是Servlet)这一层面时,我们可以通过request获取这个keywords。获取的方式有两种:
(1) 直接使用getParameter("keywords")得到keywords参数
(2) 先使用getQueryString(),再手动解析出keywords参数
我们看看这两种方式。
(1) getParameter("keywords")
这里涉及config/server.xml中URIEncode的配置项,假设我没对tomcat作任何URIEncoding的配置,它默认使用ISO-8859-1的编码。
       当访问http://localhost/?keywords=%C6%A1%BE%C6后,我们试图打印出getParameter("keywords")的值,你猜看到什么?乱码!
我们试图质问tomcat:“为什么是乱码?!如果我输入的keywords是“啤酒”这样的字符,得到乱码我可以接受,但是我输入的可是“%C6%A1%BE%C6”这样一串ISO-8859-1编码的字符啊!
有人猜测,那是浏览器在搞鬼,浏览器发送的不是“%C6%A1%BE%C6”这样的可见字符的,而是发送“啤酒”这个非ascii字符(当然,我们应该理解本质上传送的“啤酒”肯定是“啤酒”的某某编码格式的字节码,这个编码可以是常见的GBK或UTF-8)。
但是,其实不是浏览器搞鬼,浏览器发送的就是“%C6%A1%BE%C6”,你可以通过打印request.getQueryString();看到,它输出“keywords=%C6%A1%BE%C6”。
那到底是怎么回事呢?
源于tomcat对表单提交的参数(包括Get方式和Post方式)有个UDecode类的处理过程。什么是UDecode类的处理过程,详细你可以看tomcat源码的UDecode类,这里用简单的一句话概括UDecode类做的事情:修改request中的parameter(包括get方式的url参数的value和post方式的application/x-www-form-urlencoded的参数的value)的字节, 将每1个“%HH”(占3个字节)变成“0xHH”(占1个字节),且将加号"+"(占1个字节)变成空格“ ”(占1个字节)。下面的图直观的描述了这个UDecode过程:
http://hiphotos.baidu.com/atell/pic/item/a7c3ff36a0cb837d5ab5f5e7.jpg
我们看到6个字节的“%D6%D0”变成了2个字节的“[0xD6][0xD0]”,我用中括号“[ ]”来表示其中的内容合起来是一个字节。
     
到这里,我们至少知道了tomcat有个UDecode的过程,所以我们从中推理出这样的一个现象:客户端发送的keywords参数无论是啤酒的GBK字节码“[0xC6][0xA1][0xBE][0xC6]”还是啤酒的GBKURLEncode字符“%C6%A1%BE%C6”,经过tomcat的UDecode后,到变成前者,即“[0xC6][0xA1][0xBE][0xC6]”。

说到这,我再次问上面一开始的那个问题:getParameter("keywords")的值为什么是乱码?我给个提示:和UDecode有关!答案现在还不是很明显,但我们脑海可能浮现了这幅图:从UDecode的结果“[0xC6][0xA1][0xBE][0xC6]”到getParameter("keywords")的乱码。
http://hiphotos.baidu.com/atell/pic/item/e26677ee780ad17b24979147.jpg
你想到问号的部分是什么吗?很抽象地为你解开答案:
http://hiphotos.baidu.com/atell/pic/item/bc15c915c87c39474890a755.jpg

所以,getParameter("keywords")的值为什么是乱码?因为上面的bytes是GBK的字节码,而tomcat错误地将bytes作为ISO-8859-1进行解码了!难怪keywords会是乱码!

这...是tomcat的错吗?坦诚说不是,因为上面“String keywords = new String(bytes,"ISO-8859-1");”中的编码"ISO-8859-1"是可配置的,大家还记得config/server.xml中的URIEncode配置项吧?就是这个URIEncode配置项,决定是上面的式子用什么编码。

到了这里,大家都清楚了,设置配置项URIEncode=“GBK”就可以用getParameter("keywords")得到正确的keywords:“啤酒”。

另外配置项useBodyEncodingForURI使得
http://wiki.apache.org/tomcat/FAQ/CharacterEncoding#Q2
http://confluence.atlassian.com/display/DOC/Configuring+Tomcat%27s+URI+encoding
-------------------------------------------------------------------------------------------------------------------------






现在,我问大家一个问题,当你知道,浏览器无论访问“http://localhost/?keywords=%C6%A1%BE%C6” 还是 “http://localhost/?keywords=[0xC6][0xA1][0xBE][0xC6]”,tomcat都会将keywords变成“[0xC6][0xA1][0xBE][0xC6]”后,大家觉得要怎么去解码还原keywords为“啤酒”呢?
相信答案大家都很一致:
byte[] bit = new byte[]{(byte)0xD6,(byte)0xD0}; "中"的字节码,是URLDecode之后的字节码
String w = new String(bit, "GBK");  用配置的URIEncoding将其解码,变成字符"中"
String ISOkeywords = request.getParameter("keywords");
String keywords = null;
request.getQueryString();//keywords=%C6%A1%BE%C6
if(StringUtil.isNotBlank(ISOkeywords)){
try {
keywords = new String(ISOkeywords.getBytes("ISO-8859-1"), "GBK");











http://hiphotos.baidu.com/atell/pic/item/cae89d92b03b0ccba877a40f.jpg

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-331436-1-1.html 上篇帖子: Tomcat 的一些笔记 下篇帖子: Tomcat 与 cas 集成
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表