推广 热搜: csgo  vue  angelababy  2023  gps  新车  htc  落地  app  p2p 

URL编码与解码原理

   2023-07-25 网络整理佚名2160
核心提示:文档对Url的编解码问题做出了详细的建议,指出了哪些字符需要被编码才不会引起Url语义的转变,以及对为什么这些字符需要编码做出了相应的解释。下面列出了这三个函数的安全字符(即函数不会对这些字符进行编码)大部分应用程序均能处理这种非标准实现的Url编码,但是在客户端中,并没有一个函数能够将+号解码成空格,只能自己写转换函数。

通常,如果某些东西需要编码,则意味着某些东西不适合传输。 原因有很多。 例如,尺寸太大并且包含私人数据。 对于Url来说,之所以要进行编码,是因为Url中的某些字符会造成歧义。

例如Url参数字符串使用key=value键值对传递参数,键值对之间用&符号分隔,如/s?q=abc&ie=utf-8。 如果你的值字符串中包含=或&,那么必然会导致接收Url的服务器解析错误,所以你必须对不明确的&和=符号进行转义,即对它们进行编码。

再比如,Url的编码格式是ASCII码,这意味着Url中不能包含任何非ASCII字符,比如中文。 否则,如果客户端浏览器和服务器浏览器支持的字符集不同,中文可能会出现问题。

Url编码的原理是用安全字符(没有特殊用途或特殊含义的可打印字符)来表示那些不安全字符。

预备知识:URI的意思是统一资源标识符,通常我们所说的URL只是URI的一种。 典型的 URL 格式如下。 下面提到的URL编码实际上应该指的是URI编码。

foo://:8042/over/there?name=#nose

\_/ \/ \/\/ \__/

| | | | |

路径查询

哪些字符需要编码

文档规定Url中只允许使用英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符。 该文档对Url的编码和解码提出了详细的建议,指出了哪些字符需要进行编码以免改变Url的语义,并解释了为什么需要对这些字符进行编码。

US-ASCII 字符集中没有相应的可打印字符:URL 中只允许使用可打印字符。 US-ASCII码中的10-7F字节全部代表控制字符,这些字符不能直接出现在Url中。 同时,对于80-FF字节(ISO-8859-1),由于已经超出了US-ACII定义的字节范围,所以不能放在Url中。

保留字符:Url可以分为几个组成部分,如协议、主机、路径等。一些字符(:/?#[]@)用于分隔不同的组成部分。 例如:冒号用于分隔协议和主机,/用于分隔主机和路径,? 用于分隔路径、查询参数等。还有一些字符(!$&'()*+,;=)用于分隔各个组成部分。 例如,=用于表示查询参数中的键值对,&符号用于分隔查询中的多个键值对。 当组件中的普通数据包含这些特殊字符时,需要对其进行编码。

以下字符被指定为保留字符: ! * '(); : @ & = + $ , / ? #[]

不安全字符:还有一些字符直接放在 Url 中时可能会导致解析器产生歧义。 由于多种原因,这些字符被认为是不安全的。

需要注意的是,对于Url中的合法字符,编码和不编码是等价的,但是对于上述字符,如果不进行编码,可能会造成Url语义的差异。 因此,对于Url来说,未编码的Url中只能出现常见的英文字符和数字、特殊字符$-_.+!*'()和保留字符。 其他字符在出现在 URL 中之前需要进行编码。

但由于历史原因,仍然存在一些非标准的编码实现。 例如,对于~符号,虽然文档规定波浪号符号~不需要Url编码,但是仍然有很多老的网关或者传输代理会对它进行编码。

如何对Url中的非法字符进行编码

Url编码通常也称为百分号编码(Url,也称为-),因为它的编码方法非常简单,使用%百分号加两个字符——代表一个字节的十六进制形式。 URL编码默认使用的字符集是US-ASCII。 比如US-ASCII码中a对应的字节是0x61,那么Url编码就会得到%61,我们在地址栏输入%61%62%63,其实相当于在网上搜索abc。 又比如@符号在ASCII字符集中对应的字节是0x40,Url编码后得到的结果是%40。

对于非ASCII字符,需要使用ASCII字符集的超集进行编码得到对应的字节,然后对每个字节进行百分比编码。 对于字符,RFC文档建议使用utf-8编码得到对应的字节,然后对每个字节进行百分比编码。 例如“中文”使用UTF-8字符集得到的字节为0xE4 0xB8 0xAD 0xE6 0x96 0x87,Url编码后得到“%E4%B8%AD%E6%96%87”。

如果某个字节对应于 ASCII 字符集中的非保留字符,则该字节不需要用百分号表示。 例如“Url编码”,使用UTF-8编码得到的字节为0x55 0x72 0x6C 0xE7 0xBC 0x96 0xE7 0xA0 0x81,由于前三个字节对应的是ASCII中的非保留字符“Url”,所以这三个字节可以用非保留字符“Url”来表示。 最终的Url代码可以简化为“Url%E7%BC%96%E7%A0%81”,当然如果使用“%55%72%6C%E7%BC%96%E7%A0%81”也是可以的。

由于历史原因,有些Url编码实现并没有完全遵循这个原则,下面会提到。

和 之间的区别

提供了三对函数对Url进行编码,得到合法的Url,分别是 / 、 / 和 / 。 由于解码和编码过程是可逆的,因此这里仅解释编码过程。

这三个编码函数——、——用于将不安全、非法的Url字符转换为合法的Url字符表示,它们有以下区别。

安全字符不同:

下面列出了这三个函数的安全字符(即函数不会对这些字符进行编码)

兼容性不同:该功能从1.0就已经存在,另外两个功能是1.5引入的。 但由于1.5已经很流行了,所以使用and其实不存在兼容性问题。

字符的编码方式不同:三个函数对于ASCII字符的编码方式相同,都是用一个百分号+两个十六进制字符来表示。 但对于字符来说,编码方式是%uxxxx,其中xxxx是一个4位的十六进制字符,用来表示一个字符。 W3C 已弃用此方法。 但这种编码语法仍然保留在 ECMA-262 标准中。 并使用 UTF-8 对非 ASCII 字符进行编码,然后对它们进行百分比编码。 这是 RFC 推荐的。 因此,建议尽可能使用这两个函数来代替编码。

适用场合不同:它用于对完整的URI进行编码,但它用于对URI的组成部分进行编码。 从上面提到的安全字符范围表中,我们会发现编码字符的范围大于 。 上面我们提到,保留字符一般用于分隔URI组件(一个URI可以分为多个组件,参见预备部分)或子组件(如URI中查询参数的分隔符),如:字符用于分隔和托管,? 用于分隔主机和路径。 由于操作的对象是一个完整的URI,这些字符在URI中有特殊的用途,所以这些保留字符不会被编码,否则含义就会改变。

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

表单提交

当提交 Html 表单时,每个表单字段在发送之前都会进行 Url 编码。 由于历史原因,表单使用的Url编码实现不符合最新标准。 例如,空格使用的编码不是%20,而是+号。 如果使用Post方法提交表单,我们可以看到HTTP 中有一个-Type,其值为/x-www-form-。 大多数应用程序都可以处理Url编码的这种非标准实现,但是在客户端中,没有可以将+号解码为空格的函数,因此只能自己编写转换函数。 另外,对于非ASCII字符,使用的编码字符集取决于当前文档使用的字符集。例如我们在Html的head中添加

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

这样浏览器就会用它来渲染这个文档(注意,当HTML文档中没有设置这个meta标签时,浏览器会根据当前用户的喜好自动选择字符集,用户也可以强制当前网站使用指定的字符集)。 提交表单时,URL编码使用的字符集是.

我在使用的时候遇到了一个很困惑的问题(为什么下面会提到),就是我在使用的时候发现它的编码结果和我想象的有很大的出入。 下面是我的示例代码:

DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
    head>
    <body>
        <script type="text/javascript">
            document.write(encodeURI("中文"));
        script>
    body>
html>

运行结果输出为%E6%B6%93%EE%85%9F%E6%9E%83。 显然这不是使用UTF-8字符集的Url编码的结果(网上搜索“中文”,Url显示%E4%B8%AD%E6%96%87)。

所以我当时就想是不是和页面编码有关,但是我发现一般情况下,如果使用Url编码的话,是不会得到这个结果的。 后来终于发现问题是由于页面文件存储所使用的字符集与meta标签中指定的字符集不一致造成的。 编辑器默认使用UTF-8字符集。 也就是说,文件实际存储时使用的是UTF-8字符集。 但由于是在meta标签中指定的,此时浏览器会对文档进行相应的解析,“中文”字符串自然就会出错,因为“中文”字符串用UTF-8编码后得到的字节是0xE4 0xB8 0xAD 0xE6 0x96 0x87,而这6个字节被浏览器解码后,就会得到另外三个汉字“琼枃”(GBK中的一个汉字占两个字节) bytes),这三个汉字传入函数后,结果为%E6%B6%93%EE%85%9F%E6%9E%83。 因此,仍然使用UTF-8,不会受到页面字符集的影响。

对于包含中文的Url的处理,不同的浏览器有不同的表现。 例如,对于 IE,如果选中高级设置“始终以 UTF-8 发送 Url”,则 Url 路径部分中的中文将以 UTF-8 进行 Url 编码并发送到服务器,而查询参数中的中文部分将以系统默认字符集进行 Url 编码。 为了保证最大的互操作性,建议放置在Url中的所有组件都显式指定Url编码的字符集,而不是依赖于浏览器的默认实现。

另外,很多HTTP监控工具或者浏览器地址栏在显示Url时,都会自动对Url进行一次解码(使用UTF-8字符集)。 但实际上发送到服务器的原始Url仍然是经过编码的。 您可以通过地址栏上的 .href 来查看它。 在学习Url编解码器时,不要被这些错觉所迷惑。

 
反对 0举报 0 收藏 0 打赏 0评论 0
 
更多>同类资讯
推荐图文
推荐资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报
Powered By DESTOON