• URL编码


    URL的特性

    可移植性

      URL需要通过各种不同的协议来传送,那么组成URL的字符就要求被所有网络协议所识别,只能使用通用的安全字母表中的字符。

      URL字符使用的是US-ASCII 字符集,也叫做标准7位ASCII

    可阅读性

      US-ASCII中有些字符虽然是可移植的,但因为不可见、不可打印,无法阅读,所以也不能在 URL 中使用。7位ASCII共有128个字符,其中33个不可打印字符,95个为可打印字符

    完整性

      URL 中包含除通用的安全字符以外,有时候还希望包含一些非安全字符,比如汉字。这就需要我们对这些非安全字符进行编码。编码成ASCII码中安全的字符。

    另外,ASCII码95个可打印字符中有些在URL中被用于特殊用途或者留待将来用于特殊用途。这些特殊字符往往用来分隔URI组件或者子组件的分隔符。

      Url可以划分成若干个组件,协议、主机、路径等。

      有一些字符(:/?#[]@)是用作分隔不同组件的。例如:冒号用于分隔协议和主机,/用于分隔主机和路径,?用于分隔路径和查询参数,等等。

      还有一些字符(!$&'()*+,;=)用于在每个组件中起到分隔作用的,如=用于表示查询参数中的键值对,&符号用于分隔查询多个键值对。

      服务器端在解析URL时,就是使用这些具有特殊意义的分割符将URL解析成各个组件(协议,主机,路径,参数字符串)或者子组件(参数字符串中的键和值)

      但这些特殊字符用于特殊用途之外时,就会造成歧义,也需要进行编码。比如=用于分割键和值时(如a=eee),不需要进行编码,但如果=作为字符串值中的一个字符时(如a=ee=e, ee=e为一个字符串值),就必须要编码

    总结:组成URL的字符只能是7位ASCII码中的95个可打印字符。

              当URL中包含有95个可打印字符以外的字符时,则必须对这些字符进行编码

         当95个可打印字符中的特殊字符被用于特殊用途时,不能被编码,但如果被用于非特殊用途时也必须要进行编码,如上面=的用途。

              当95个可打印字符中没有特殊意义的安全字符,可以编码,也可以不编码

    URL中的特殊字符(保留及受限字符)

    URL的编码机制

    URL的编码机制非常简单。

    一个字符在字符集中的编码值就是一个数字。这个数字可能由一个或多个字节组成。

    URL编码就是在这个字符对应的编码值的每个字节前加上%,并且用16进制来表示。

    比如如果要编码a,a在ASCII字符集中的编码值为97(10进制),ASCII字符集都是单字节字符,那么二进制表示就是 0110 0001,十六进制表示就是61,所以进行编码后就是%61

    即使是同一个字符,在不同的字符集中可能具有不同的编码值,而且可能由不同数目的字节组成。所以使用不同的字符集对字符进行的编码也不相同。

    比如 "春" 字,在utf-8中的编码值为 "E6 98 A5" ,由3个字节组成,URL编码后就是"%E6%98%A5"。

    而在GB2312中,"春" 字的编码值为"B4 BA", 所以URL编码后就是"%B4%BA"

    由于历史的原因,有一些Url编码实现并不完全遵循这样的机制

    URL的编码的现状

    网络标准RFC 1738对URL的字符组成做了硬性规定,没有规定具体的编码方法和编码字符集,而是交给应用程序(浏览器)自己决定。这导致"URL编码"成为了一个混乱的领域。

    前辈们的关于浏览器的默认URL编码的结论如下。随着浏览器版本的更新以下结论可能并不适应,仅供参考,了解下现状。

    结论1就是,网址路径的编码,用的是utf-8编码。 (测试方法:浏览器中直接输入网址)

    结论2就是,查询字符串的编码,用的是操作系统的默认编码。(测试方法:浏览器中直接输入网址)

    结论3就是,GET和POST方法的编码,用的是网页的编码。(测试方法:在已打开的网页上,直接用Get或Post方法发出HTTP请求)

      这时的编码方法由网页的编码决定,也就是由HTML源码中字符集的设定决定。

      <meta http-equiv="Content-Type" content="text/html;charset=xxxx">

    结论4就是,在Ajax调用中,IE总是采用操作系统的默认编码,而Firefox总是采用utf-8编码。(测试方法:由Javascript生成HTTP请求,也就是Ajax调用)

    由此可见,应用程序自己进行URL编码时,在服务器端无法判断使用了那种字符集进行的编码,所以在解码时就可能使用了错误的字符集进行解码,从而造成乱码。

    解决这种问题的方法就是手动对URL用已知的字符集进行编码,不给应用程序插手的机会。如使用javaxcript中的encodeURI和encodeURIComponent等进行编码。

    Javascript中的escape, encodeURI和encodeURIComponent的区别

    安全字符不同:

    • escape(69个):*/@+-._0-9a-zA-Z
    • encodeURI(82个):!#$&'()*+,/:;=?@-._~0-9a-zA-Z
    • encodeURIComponent(71个):!'()*-._~0-9a-zA-Z

      encodeURI比encodeURIComponent多了11个安全字符  # $ & + , / : ; = ? @

    对Unicode字符的编码方式不同:

      对于ASCII字符,这三个函数的编码方式相同,均是使用百分号+两位十六进制字符来表示。

      对于Unicode字符,escape的编码方式是%uxxxx,其中的xxxx是用来表示unicode字符的4位十六进制字符。这种方式已经被W3C废弃了。但是在ECMA-262标准中仍然保留着escape的这种编码语法。encodeURI和encodeURIComponent则使用UTF-8对非ASCII字符进行编码,然后再进行百分号编码。这是RFC推荐的。因此建议尽可能的使用这两个函数替代escape进行编码。

    适用场合不同:

      encodeURI被用作对一个完整的URI进行编码,而encodeURIComponent被用作对URI的一个组件进行编码。

      从上面提到的安全字符范围表格来看,我们会发现,encodeURIComponent编码的字符范围要比encodeURI的大。我们上面提到过,保留字符一般是用来分隔URI组件(一个URI可以被切割成多个组件,参考预备知识一节)或者子组件(如URI中查询参数的分隔符),如:号用于分隔scheme和主机,?号用于分隔主机和路径。由于encodeURI操纵的对象是一个完整的的URI,这些字符在URI中本来就有特殊用途,因此这些保留字符不会被encodeURI编码,否则意义就变了。

      组件内部有自己的数据表示格式,但是这些数据内部不能包含有分隔组件的保留字符,否则就会导致整个URI中组件的分隔混乱。因此对于单个组件使用encodeURIComponent,需要编码的字符就更多了。

      

    总结:

      escape函数基本上被废弃,尽量不要使用。

      encodeURI和encodeURIComponent都是使用utf-8进行URL编码。并且对各自的安全字符不会进行编码。两者的安全字符范围不同,如前面所说。

      encodeURI不会对URL中的某些特殊字符进行编码,比如:/?&=@等等。因此可用于对整个URL进行编码。这里说的某些字符就是encodeURI比encodeURIComponent多了的11个安全字符

      encodeURIComponent会对URL中的某些特殊字符进行编码,只能对某个URL组件或者子组件进行编码。比如传递参数中的值。

    实例

    由以上实例可以看出,当URL组件或者子组件内部不包含某些特殊字符时,可以直接使用encodeURI对整个URL进行编码,

    如果URL当URL组件或者子组件内部包含某些特殊字符时,则不能使用encodeURI对整个URL进行编码,而是需要使用encodeURIComponent分别对各个组件或者子组件进行编码

    另外,很多HTTP监视工具或者浏览器地址栏等在显示Url的时候会自动将Url进行一次解码(使用UTF-8字符集),这就是为什么当你在Firefox中访问Google搜索中文的时候,地址栏显示的Url包含中文的缘故。但实际上发送给服务端的原始Url还是经过编码的。你可以在地址栏上使用Javascript访问location.href就可以看出来了。在研究Url编解码的时候千万别被这些假象给迷惑了。

  • 相关阅读:
    python模块搜索路径
    Python数据结构
    Python文件类型
    Python循环语句
    Python条件语句
    python配置文件操作——configparser模块
    python 加密方式(MD5&sha&hashlib)
    python MySQL 获取全部数据库(DATABASE)名、表(TABLE)名
    python sqlite3查看数据库所有表(table)
    027.MFC_映射消息
  • 原文地址:https://www.cnblogs.com/gaoBlog/p/11589534.html
Copyright © 2020-2023  润新知