地址栏中文参数

时间:2022-08-27 22:07:51
地址栏中文参数

先解释下,什么是地址栏用中文参数。地址栏用中文参数的更确切的说法应该是,GET请求中参数直接使用中文字符串,而不做任何URLEncode。

 

举个例子,在www.google.com中搜索“我”,请求是用的GET方式发送的,页面打开后,地址栏(用的Safari,苹果上的网页浏览器)显示的是“http://www.google.com/search?client=safari&rls=zh-cn&q=我&ie=UTF-8&oe=UTF-8”,这就是一个GET请求参数直接用中文字符串的例子。用IE的同志注意了,上面的链接点击后到达的页面是不正常的,显示的不是搜索“我”的页面,把这个链接复制了,然后粘贴到IE的地址栏里,访问到的页面也是不正常的,问题是这次的不正常和刚才的不正常还不一样。这个例子告诉我们,地址栏用中文参数还真的有可能是“不可能的任务”。

我先分析下问题产生的原因,然后再谈一谈解决这个问题的最佳实践。

原因分析:

如果我们的用户都用的是一种浏览器,那么问题要简单的多,只要弄明白这个浏览器到底是怎么表现的,针对这个做一些编码的转换就行了,但是问题就在于,我们的用户用了至少是IE,Firefox和Safari这三种浏览器(注:奥游和腾讯TT本质都是IE),而这三个浏览器的表现很不一样。

1.首先说Firefox,在Firefox的地址栏中用中文参数,它的表现是用UTF-8编码进行URLEncode,并且把encode之后得到的字符串显示在地址栏。

2.然后是Safari,Safari和Firefox基本一致,也是用UTF-8编码进行URLEncode,但是Safari会自作聪明一点,如果参数里有它认识的URLEncode后的字符串,如“%E6%88%91”(注:这段是“我”经过URLEncode得到的),什么是Safari认识的呢,就是可以用UTF-8编码进行URLEncode得到的,它就会恢复原始中文的显示。所以开篇safari中得到的地址栏链接就是含中文的。

3.最后是IE,IE表现的最无语,上面大家都看到了,同样的链接,在页面中打开和在地址栏输入得到的都不一样。这是怎么造成的呢?IE在处理中文参数的时候,对于直接输入在地址栏里的,使用的是系统平台对应的编码,比如我们用的Windows中文版,那就是用的GB18030编码,而对于页面链接里的,使用的是页面的编码,比如这篇文章的页面编码是UTF-8,所以从这个页面打开上面的链接,中文是用UTF-8编码进行URLEncode的,而在地址栏,直接输入,使用的是GB18030的编码。处理的不同也就罢了,但是不能在地址栏里一点区别也看不出来阿,所以IE是表现的最无语的。

那么,如何解决这个问题呢?处理过浏览器兼容问题的同志应该会想到对不同浏览器区别对待,这个想法是可行的,因为用户用的什么浏览器在服务端是可以获得的。但是IE使这个问题复杂了许多,我们并不知道用户是点击的页面中的链接,还是在地址栏里直接输入的,而且我们也未必知道页面的编码和系统的语言环境。

看起来,我们只能根据原始内容“动态识别字符编码”了。其实“动态识别字符编码”对于我们来说并不陌生,我们的浏览器都是支持我们自己指定用什么编码来打开页面的,用的最多的情况是Web邮箱,有的邮件我们可能要换一个编码才能看,否则全是乱码,网页的编码在没有指定的情况下,浏览器会猜一个编码,这就是“动态识别字符编码”。另外,有些文本编辑器也是支持多种文件编码的,打开一个文件时,也会“动态识别字符编码”。

如何实现“动态识别字符编码”呢?cpdetector是一个开源项目,这个项目的主页是http://cpdetector.sourceforge.net/,这个项目提供了“动态识别字符编码”我已经适用,基本是可以识别的。

这里还需要解释一个服务器端用Java相关技术时的问题,Tomcat默认的URIEncodeing用的是ISO-8859-1编码,这造成的是在Firefox或Safari这样的不是很无语的浏览器上,对于中文数据,POST请求和GET请求也表现的不一样,如果页面用UTF-8编码,GET时是乱码的。这事实上是另一个“地址栏用中文参数”的问题,这个问题我们一般搜索到的解决办法是修改tomcat的URIEncodeing参数为UTF-8。

当然我们不是一定要做这样一个操作,我们既然知道数据是用ISO-8859-1编码的,我们大可getBytes("ISO-8859-1")。但是我这样做,然后配合用cpdetector“动态识别字符编码”的方案,又发现了问题,有时候IE下对一些字符串做了一些编码转换操作之后就出现问题了,我试出来的例子是,在编码是UTF-8的页面上提供了一个包含参数为“我是谁”的链接,点击后,经过了getBytes("ISO-8859-1")和cpdetector“动态识别字符编码”,得到了我是口(注:口是个表示不能识别的框框),有些参数直接识别字符编码都失败,比如“你我他”被识别成了“x-EUC-TW”。这些问题基本是不可解决的。我也尝试了修改tomcat的URIEncodeing参数为UTF-8,问题依然,而且cpdetector居然也识别不出来直接输入地址栏时的编码GB18030。这终于是个名符其实的不可能的任务了。

最佳实践:

由于无语的IE,我们放弃了地址栏用中文参数,我们乖乖的使用URLEncode,但是URLEncode就可以了吗?答案是否定的,要知道,自作聪明的Safari会吧URLEncode后的字符串还原称原来的中文,那么Safari的地址栏里常常是有中文的,那么一个Safari用户把这个链接发给一个IE用户,后者不又Shit了吗?所以我们要对中文字符串进行两次URLEncode,由于服务器会自动进行一次URLDecode,所以我们在服务端编程再进行一次URLDecode。这就是最佳实践,放弃了友好的URL,放弃了简洁和清晰,技巧近乎变态,但这是唯一的能够充分避免无效链接的方法。校园网络套餐课程的文件柜中的中文参数就采取了这种方法。

总结:

本篇基本实践了“地址栏用中文参数”的努力中的各种问题,实践证明“地址栏用中文参数”是不可能的任务,然后以一种极度为用户负责的态度提出了一个有点变态的最佳时间。

最后忍不住说一句:IE给程序开发造成的不便,绝对不仅仅是这个,下次请个做前端开发的同志谈一谈。