`
wdp107
  • 浏览: 141486 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

关于不同浏览器对URL编码的分析

阅读更多
先来看看三个url:

url1. http://hi.baidu.com/爱宝的妍

url2. http://hi.baidu.com/%E7%88%B1%E5%AE%9D%E7%9A%84%E5%A6%8D (UTF-8 编码)

url3. http://hi.baidu.com/%B0%AE%B1%A6%B5%C4%E5%FB (GBK 编码)

这三个url指向同一个网页,而且都能够访问。其实,如果你的浏览器是中文环境下的,IE设置“以UTF8发送URL”,那么在IE里输入 url1,服务器端得到的是url2;在firefox里输入url1,服务器端得到的是url3。这是为什么呢?听下文分解(分析部分内容转自 http://blog.csdn.net/yzhz/archive/2007/07/03/1676796.aspx)。

一、问题:
编码问题是JAVA初学者在web开发过程中经常会遇到问题,网上也有大量相关的文章介绍,但其中很多文章并没有对URL中使用 了中文等非ASCII的字符造成服务器后台程序解析出现乱码的问题作出准确的解释和说明。本文将详细介绍由于在URL中使用了中文等非ASCII的字符造 成乱码的问题。

1、在URL中中文字符通常出现在以下两个地方:
(1)、Query String中的参数值,比如http://search.china.alibaba.com/search /offer_search.htm?keywords=中国
(2)、servlet path,比如:http://search.china.alibaba.com/selloffer/中国.html


2、出现乱码问题的原因主要是以下几方面:
(1)、浏览器:我们的客户端(浏览器)本身并没有遵循URI编码的规范 (http://www.w3.org/International/O-URL-code.html)。
(2)、Servlet服务 器:Servlet服务器的没有正确配置。
(3)、开发人员并不了解Servlet的规范和API的含义。

二、基础知识:
1、一个http请求经过的几个环节:
浏览器(ie firefox)【get/post】------------>Servlet服务器 ------------------------------->浏览器显示
编码                   解码成unicode,然后将显示的内容编码          解码
(1) 浏览器把URL(以及post提交的内容)经过编码后发送给服务器。
(2) 这里的Servlet服务器实际上指的是由Servlet服务器提供的servlet实现ServletRequestWrapper,不同应用服务器的 servlet实现不同,这些servlet的实现把这些内容解码转换为unicode,处理完毕后,然后再把结果(即网页)编码返回给浏览器。
(3) 浏览器按照指定的编码显示该网页。

          当对字符串进行编码和解码的时候都涉及到字符集,通常使用的字符集为ISO8859-1、GBK、UTF-8、UNICODE。


2、URL的组成:
域名:端口/contextPath/servletPath/pathInfo?queryString
说 明:

1、ContextPath是在Servlet服务器的配置文件中指定的。
对于weblogic:
contextPath是在应用 的weblogic.xml中配置。
<context-root>/</context-root>

对 于tomcat:
contextPath是在server.xml中配置。
<Context path="/" docBase="D:/server/blog.war" debug="5" reloadable="true" crossContext="true"/>

对于jboos:
contextPath是在应用的jboss-web.xml中配置。
<jboss-web>
<context-root>/</context-root>
</jboss-web>

2、ServletPath是在应用的web.xml中配置。
<servlet-mapping>
<servlet-name>Example</servlet-name>
<url-pattern>/example/*</url-pattern>
</servlet-mapping>

2、Servlet API
我们使用以下servlet API获得URL的值及参数。
request.getParameter("name");           // 获得queryString的参数值(来自于get和post),其值经过Servlet服务器URL Decode过的
request.getPathInfo();                  // 注意:pathinfo返回的字符串是经过Servlet服务器URL Decode过的。
requestURI = request.getRequestURI(); // 内容为:contextPath/servletPath/pathinfo 浏览器提交过来的原始数据,未被Servlet服务器URL Decode过。


3、开发人员必须清楚的servlet规范:
(1) HttpServletRequest.setCharacterEncoding()方法 仅仅只适用于设置post提交的request body的编码而不是设置get方法提交的queryString的编码。该方法告诉应用服务器应该采用什么编码解析post传过来的内容。很多文章并没 有说明这一点。
(2) HttpServletRequest.getPathInfo()返回的结果是由Servlet服务器解码(decode)过的。
(3) HttpServletRequest.getRequestURI()返回的字符串没有被Servlet服务器decoded过。
(4) POST提交的数据是作为request body的一部分。
(5) 网页的Http头中ContentType("text/html; charset=GBK")的作用:
(a) 告诉浏览器网页中数据是什么编码;
(b) 表单提交时,通常浏览器会根据ContentType指定的charset对表单中的数据编码,然后发送给服务器的。
这里需要注意的是:这里所说的ContentType是指http头的ContentType,而不是在网页中meta中的ContentType。


三、下面我们分别从浏览器和应用服务器来举例说明:
URL:http://localhost:8080/example/中 国?name=中国
汉字     编码        二进制表示
中国     UTF-8       0xe4 0xb8 0xad 0xe5 0x9b 0xbd[-28, -72, -83, -27, -101, -67]
中国     GBK         0xd6 0xd0 0xb9 0xfa[-42, -48, -71, -6]
中国     ISO8859-1 0x3f,0x3f[63, 63]信息失去


(一)、浏览器
1、GET方式提交,浏览器会对URL进行URL encode,然后发送给服务器。
(1) 对于中文IE,如果在高级选项中选中总以UTF-8发送(默认方式),则PathInfo是URL Encode是按照UTF-8编码,QueryString是按照GBK编码。
http://localhost:8080/example/中 国?name=中国
实际上提交是:
GET /example/%E4%B8%AD%E5%9B%BD?name=%D6%D0%B9%FA

(1) 对于中文IE,如果在高级选项中取消总以UTF-8发送,则PathInfo和QueryString是URL encode按照GBK编码。
实际上提交是:
GET /example/%D6%D0%B9%FA?name=%D6%D0%B9%FA

(3) 对于中文firefox,则pathInfo和queryString都是URL encode按照GBK编码。
实际上提交是:
GET /example/%D6%D0%B9%FA?name=%D6%D0%B9%FA

很显然,不同的浏览器以及同一浏览器的不同设置,会影响最终URL中PathInfo的编码。对于中文的IE和FIREFOX都是采用GBK编码 QueryString。

小结:解决方案:
1、URL中如果含有中文等非ASCII字符,则浏览器会对它们进行URLEncode。为了避免浏览器采用了我们不希望 的编码,所以最好不要在URL中直接使用非ASCII字符,而采用URL Encode编码过的字符串%.
比如:
URL:http://localhost:8080 /example/中国?name=中国
建议:
URL:http://localhost:8080/example/%D6%D0 %B9%FA?name=%D6%D0%B9%FA

2、我们建议URL中PathInfo和QueryString采用相同的编码,这样对服务器端处理的时候会更加简单。

2、还有一个问题,我发现很多程序员并不明白URL Encode是需要指定字符集的。不明白的人可以看看这篇文档:http://gceclub.sun.com.cn/Java_Docs/html /zh_CN/api/java/net/URLEncoder.html

2、 POST提交
对于POST方式,表单中的参数值对是通过request body发送给服务器,此时浏览器会根据网页的ContentType("text/html; charset=GBK")中指定的编码进行对表单中的数据进行编码,然后发给服务器。
在服务器端的程序中我们可以通过 Request.setCharacterEncoding() 设置编码,然后通过request.getParameter获得正确的数据。

解决方案:
1、从最简单,所需代价最小来看,我们对URL以及网页中的编码使用统一的编码对我们来说是比较合适的。
如果不使用统一 编码的话,我们就需要在程序中做一些编码转换的事情。这也是我们为什么看到有网络上大量的资料介绍如何对乱码进行处理,其中很多解决方案都只是一时的权宜 之计,没有从根本上解决问题。


(二)、Servlet服务器
Servlet服务器实现的Servlet遇到URL和POST提交的数据中含有%的字符串,它会按照指定的字符集解码。下面两个Servlet方法返回 的结果都是经过解码的:
request.getParameter("name");
request.getPathInfo();

这里所说的"指定的字符集"是在应用服务器的配置文件中配置。

(1) tomcat服务器
对于tomcat服务器,该文件是server.xml
<Connector port="8080" protocol="HTTP/1.1"
maxThreads="150" connectionTimeout="20000"
redirectPort="8443" URIEncoding="GBK"/>
URIEncoding告诉服务器servlet解码URL时采用的编码。

<Connector port="8080" ... useBodyEncodingForURI="true" />
useBodyEncodingForURI 告诉服务器解码URL时候需要采用request body指定的编码。

(2) weblogic服务器
对于weblogic服务器,该文件是weblogic.xml
<input-charset>
<java-charset-name>GBK</java-charset-name>
</input-charset>

(三)浏览器显示
浏览器根据http头中的ContentType("text/html; charset=GBK"),指定的字符集来解码服务器发送过来的字节流。我们可以调用 HttpServletResponse.setContentType()设置http头的ContentType。

总结:
1、URL中的PathInfo和QueryString字符串的编码和解码是由浏览器和应用服务器的配置决定的,我们的程序不能设 置,不要期望用request.setCharacterEncoding()方法能设置URL中参数值解码时的字符集。
所以我们建议URL中不 要使用中文等非ASCII字符,如果含有非ASCII字符的话要使用URLEncode编码一下,比如:
http://localhost:8080 /example1/example/中国
正确的写法:
http://localhost:8080/example1/example/%E4%B8%AD%E5%9B%BD
并 且我们建议URL中不要在PathInfo和QueryString同时使用非ASCII字符,比如
http://localhost:8080 /example1/example/中国?name=中国
原因很简单:不同浏览器对URL中PathInfo和QueryString编码时采 用的字符集不同,但应用服务器对URL通常会采用相同的字符集来解码。

2、我们建议URL中的URL Encode编码的字符集和网页的contentType的字符集采用相同的字符集,这样程序的实现就很简单,不用做复杂的编码转换。

到这里大家该明白url编码的原理了吧。再回过头来看看本文一开始给出的三个url。http://hi.baidu.com/爱宝的妍 属于PathInfo,所以根据IE以及Firefox默认设置,ie用utf8 encode了该url,而firefox用gbk encode的,随之服务器端得到了url2和url3不同的url。
分享到:
评论

相关推荐

    解决了浏览器URL地址栏直接输入get参数值包含中文时的urlencode编码格式问题

    并且这个格式居然不能再这个函数里面设置,导致这个结果不可控制,在不同浏览器环境下面结果不同,不能得到自己想要的格式编码。在搜索引擎里面找了很长时间,都没有找到解决这个问题的办法,没办法,只能自己手动...

    asp.net URL编码与解码

    例如Url参数字符串中使用key=value键值对这样的形式来传参,键值对之间以&符号分隔,如/s?... Url编码的原则就是使用安全的字符(没有特殊用途或者特殊意义的可打印字符)去表示那些不安全的字符。 预备知识:UR

    vivict:一个易于使用的浏览器内工具,可以对同一视频源的不同编码的视觉质量进行主观比较

    一个易于使用的浏览器内工具,可以对同一视频源的不同编码的视觉质量进行主观比较。 入门 转到 。 默认情况下,它将以不同的比特率打开来自视频的HLS测试流。 用法 屏幕分为两部分,左右部分显示左右视频源。 分割...

    php中url传递中文字符,特殊危险字符的解决方法

    我们需要在url中传递中文字符或是其它的html等特殊字符,似乎总会有各种乱,不同的浏览器对他们的编码又不一样, 对于中文,一般的做法是: 把这些文本字符串传给url之前,先进行urlencode($text)一下; 但是对于...

    大数据爬虫技术第3章 网页请求原理.ppt

    User-Agent(浏览器名称) 标识客户端身份的名称,通常页面会根据不同的User-Agent信息自动做出适配,甚至返回不同的响应内容。 Accept (传输文件类型) 指浏览器或其他客户端可以接受的MIME(Multipurpose ...

    imgix-core-js:一个JavaScript客户端库,用于使用imgix生成图像URL

    imgix-core-js是一个JavaScript库,用于使用生成图像URL,该URL可在浏览器或... 每当您将数据提供给imgix-core-js时,请确保其尚未经过URL编码,因为该库会在内部处理正确的编码。 普通JS var ImgixClient = require

    js-core:用于使用 imgix 生成图像 URL 的 JavaScript 客户端库

    @imgix/js-core是一个 JavaScript 库,用于使用生成可用于浏览器或服务器端设置的图像 URL。 ImgixClient.buildSrcSet(path, params, options) 固定图像渲染 自定义宽度 宽度公差 最小和最大宽度范围 可变品质 Web...

    Jenkins安装教程.docx

    还有一种安装方式就是将下载的war包文件部署到 servlet 容器,然后启动容器,在浏览器的URL地址栏中输入类似http://localhost:8080/jenkins/这样的地址即可。下图是安装成功后的界面(使用的是Linux+Tomcat7+Java7...

    httpism:适用于Node.js和浏览器的面向资源的HTTP客户端

    另外,httpism支持: 网址模板饼干具有代理身份验证的HTTP和HTTPS流量的HTTP代理基本认证JSON格式URL编码形式流CORS JSONP从2.x升级Httpism 3.x默认情况下返回响应的主体,而不是响应。 这是您95%的时间所需要的,...

    爱特全能网站文件专家 v2.4.rar

    爱特文件专家技巧文件列表添加Ftp://可以操作Ftp文件使用远程上传输入Url地址即可导入文件用清单功能批量操作不同目录文件,如压缩. 命名功能如果输入绝对路径还可以当移动使有时操作重要文件怕出错,文件复件让你安心...

    Web应用安全:HTTP方法.pptx

    HTTP/1.1协议中共定义了八种方法(有时也叫“动作”),来表明Request-URL指定的资源不同的操作方式 HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法。 HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE...

    java-servlet-api.doc

    Servlet与applets不同的地方是,它不运行在Web浏览器或其他图形化的用户界面上。Servlet通过servlet引擎运行在Web服务器中,以执行请求和响应,请求、响应的典型范例是HTTP协议。 一个客户端程序,可以是一个Web...

    爱特全能网站文件专家 v2.8

    爱特文件专家安装环境//可以操作Ftp文件使用远程上传输入Url地址即可导入文件用清单功能批量操作不同目录文件,如压缩. 命名功能如果输入绝对路径还可以当移动使有时操作重要文件怕出错,文件复件让你安心. 谦容各种...

    IIS服务器SSI(rewrite重写)插件的帮助资料

    内容商议:向不同的语言用户或者不同的浏览器用户提供不同的文件。示例 ? 为群集式服务器架构模拟负载均衡。 定价资料 ? 45天的试用期 ? 单机版99美元 ? ISAPI_Rewrite精简版是免费的。在这里可以看到受限的细节...

    【Scrapy爬虫项目】爬取books.toscrape.com上书籍的相关信息并存储为csv文件

    虽然很多时候用view命令加载出的页面和浏览器打开的是一样的,但是前者是Scrapy爬虫下载的页面,后者是由浏览器下载的页面,有时它们是不同的。 在进行页面分析时,使用view命令更加可靠: 在命令提示符窗口输入 s

    java web 乱码 问题

    相信web站点乱码问题都曾使我们困惑加郁闷不少,在此我积累了几点解决方案,用于解决不同情况下的乱码问题,希望能对各位有些许提示作用。  首先应确定不是因为浏览器的原因导致中文乱码。  本人在刚用firefox...

    script标签的 charset 属性使用说明

    如果外部文件中的字符编码与主文件中的编码方式不同,就要用到 charset 属性。 默认的字符编码是 ISO-8859-1。 src 和 charset 属性 对特别长的 JavaScript 程序或者经常重复使用的程序来说,你可以希望将这些代码...

    web路径探测工具 7kbscan-WebPathBrute 1.5.8 (集成三字典)

    四、扫描前URL编码解决部分误报问题 1.4 至安全学员内测版2017-07-21 一、修改最大并发连接为100 二、对输入Url进行智能处理获取最后一个’/’的目录进行扫描 三、增加工作线程数显示控制停止后开始前的线程是否...

Global site tag (gtag.js) - Google Analytics