zoukankan      html  css  js  c++  java
  • URL编码

    为什么要编码?

    如果一样东西需要编码,那说明它不适合传输,原因有多种(有些字符有歧义、包含隐私数据、Size过大)。

    在 URL 中,之所以要编码,是因为有些字符会引起歧义。比如参数中的key=value键值对,当value里含有= & ? 等,就会造成 URL 服务器的解析错误。所以必须将引起歧义的符号进行转义,也就是对其进行编码。

    URL 的编码格式采用的是 ASCII 码,而不是 Unicode,也就是说 URL 中不能包含任何非 ASCII 字符,比如中文(如果客户端浏览器和服务器端浏览器支持的字符集不同,中文可能会造成问题,现在一般默认都使用 UTF-8)。

    URI的编码原则是使用安全的字符去(没有特殊用途和特殊意义的可打印字符)表示那些不安全的字符。URI 是统一资源标识,我们所说的 URL 只是 URI 的一种。

    哪些字符需要编码?

    RFC3986文档规定:URL 中只允许包含英文字母(a-zA-Z)、数字(0-9)、4个特殊字符(-_.~)、所有保留字符。

    保留字:URL 可以划分成若干组件,协议、主机、路径等
    一些字符用来分隔不同组件,比如 :/?#@
    一些字符在每个组件中分隔的,比如 &=

    不安全字符:还有些字符,当它们直接放在 URL 中时,可能会引起解析程序的歧义,原因很多。
    1.空格 URL在传输过程 用户排版时 文本处理程序在处理URL的过程 都有可能引入无关紧要的空格;或者将有意义的空格给去掉
    2.引号和<> 通常用于在普通文本中起到分隔URL的作用
    3.# 通常用于标示书签或锚点
    4.% 它本身被用作对不安全字符编码时的特殊字符,所以本身需要编码
    5.{}[]|^’ 某些网关或者传输代理会篡改这些字符

    RFC3986文档对URL的编码问题做出了详细的建议,指出哪些字符需要被编码才不会引起 URL 语义的转变,以及为什么对这些字符进行编码做出了解释。RFC3986指定了以下字符为保留字 :/?=&#@+,;()$’*![]

    需要注意:
    由于历史原因,目前存在一些不标准的编码实现,比如对于符号~ 虽然RFC3986文档规定,对于~不需要编码,但是一些老的网关或者传输代理会。比如[]也被编码了。

    对于 URL 中的合法字符,编码和不编码是等价的,但是对于上面提到的那些字符,如果不编码,那它们可能会造成 URL 语义的不同。因此,对于 URL 而言,只有普通英文字符和数字、特殊字符和保留字符,能出现在未经编码的 URL 中,其他字符都需要经过编码。

    如何编码?

    URL 编码通常被称为百分号编码(URL Encoding, also know as percent-encoding),因为它的编码方式很简单,使用 % 加上两位的字符-代表一个字节的16进制形式。

    URL 编码默认使用的字符集是 US-ASCII
    比如 a 在US-ASCII中对应的字节是 0x61,那么URL编码之后得到的就是 %61
    又如 @ 在ASCII字符集中对应的字节是 0x40,经过URL编码之后得到的是 %40

    对于非 ASCII 字符,需要使用 ASCII 字符集的超集进行编码得到相应的字节,然后再对每个字节执行百分号编码。
    对于 Unicode 字符,RFC文档建议使用 UTF-8 对其进行编码得到相应的字节,然后再对每个字节执行百分号编码。

    JS中的URL编码

    JS 提供了 3 对函数来对 URL 编码以得到合法的 URL,它们分别是:

    1. escape/unescape
    2. encodeURI/decodeURI
    3. encodeURIComponent/decodeURIComponent

    由于编码和解码是可逆的,所以这里只解释编码过程。
    这里只说后两种编码,encodeURI 和 encodeURIComponent,它两都是用 UTF-8 对非 ASCII 字符进行编码,然后再进行百分号编码的。

    encodeURI()

    目的:对 URI 进行完整编码
    所以,它对在 URI 中具有特殊含义的 ASCII 标点符号,它是不会进行转义的,比如以下11个字符 ;/?:@&=+$,#

    它不会对以下进行编码:
    1.ASCII 字母
    2.数字
    3.ASCII 标点符号,以下9个 -_.!~*()’ 【单引号不编,双引号会被编码】
    4.在 URI 中有特殊含义的 ASCII 标点符号,以下11个 ;/?:@&=+$,#

    其他字符会被编码成16进制的转义序列

    encodeURIComponent()

    目的:把字符串作为 URI 组件进行编码

    它不会对以下进行编码:
    1.ASCII 字母
    2.数字
    3.ASCII 标点符号,以下9个 -_.!~*()’ 【单引号不编,双引号会被编码 %22】

    ASCII 中的其他字符(用于分隔URI组件的标点符号)们都会被 16进制的转义序列,替换掉。

    它们的区别

    安全字符不同:
    encodeURIComponent() 假定参数是 URI 的一部分(比如协议、主机名、路径、查询字符串),所以,会转义用于分隔 URI 各个部分的标点符号。
    所以,如果待编码的字符中含有分隔符 ? & # 等时,则应该用 encodeURIComponent()

    适用场合不同:
    encodeURI 是对一个完整的 URI 进行编码
    encodeURIComponent 是对 URI 的一个组件进行编码

    表单提交

    当 HTML 表单被提交时,每个表单域都会被 URL 编码之后才发送。
    由于历史原因,表单使用的 URL 编码实现并不符合最新的标准,例如空格使用的不是 %20,而是 + 号

    参考

    http://www.w3school.com.cn/jsref/jsref_encodeuri.asp
    http://www.w3school.com.cn/jsref/jsref_encodeURIComponent.asp

    http://www.cnblogs.com/greatverve/archive/2011/12/12/URL-Encoding-Decoding.html

    RFC3986文档对URL的描述
    https://tools.ietf.org/html/rfc3986

    16进制的转义序列:
    : %3A
    / %2F
    ? %3F
    = %3D
    & %26
    空格 %20

  • 相关阅读:
    【Lucene4.8教程之五】Luke
    【Tika基础教程之一】Tika基础教程
    【Lucene4.8教程之四】分析
    【Lucene4.8教程之六】QueryParser与Query子类:如何生成Query对象
    【Lucene4.8教程之三】搜索
    Java路径问题最终解决方案—可定位所有资源的相对路径寻址
    java.util.logging.Logger基础教程
    【Lucene4.8教程之二】索引
    【Lucene4.8教程之一】使用Lucene4.8进行索引及搜索的基本操作
    【Heritrix基础教程之4】开始一个爬虫抓取的全流程代码分析
  • 原文地址:https://www.cnblogs.com/myyan/p/4838795.html
Copyright © 2011-2022 走看看