设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

每个 Web 开发者都应该知道的关于 URL 编码的知识

2013-6-26 10:03| 发布者: 红黑魂| 查看: 3384| 评论: 0|来自: 开源中国编译

摘要: 本文首先阐述了人们关于统一资源定位符(URL)编码的普遍的误读,其后通过阐明HTTP场景下的URL encoding来引出我们经常遇到的问题及其解决方案。本文并不特定于某类编程语言,我们在Java环境下阐释问题,最后从Web应 ...

不能分析解码后的URL

URL的语法只在它被解码前是有意义的,一旦解码就可能出现保留字。

例如"http://example.com/blue%2Fred%3Fand+green" 在解码前由如下部分组成:

PartValue
Schemehttp
Hostexample.com
Path segmentblue%2Fred%3Fand+green
Decoded Path segmentblue/red?and+green

这样看来, 我们是在请求一个名为"blue/red?and+green"的文件,而不是一个位于"blue"文件夹下的名为"red?and+green"的文件。

如果我们把它解码为"http://example.com/blue/red?and+green",我们将得到如下部分:

PartValue
Schemehttp
Hostexample.com
Path segmentblue
Path segmentred
Query parameter nameand green

这明显是错误的,所以,对保留字和URL各部分的分析必须在URL解码之前完成。这意味着URL重写过滤器不应当

在尝试匹配之前解码URL,当且仅当保留字允许进行URL编码时才可以(有时符合这种情形,有时不符合,这取决

于你的应用)。


解码后的URL不能被再编码为同样的形式

如果你解码"http://example.com/blue%2Fred%3Fand+green" 为"http://example.com/blue/red?and

+green",然后对它进行编码(哪怕使用一个对URL每一部分都很了解的编码器),你将会得到"http://example.com/blue/red?and+green",这是因为它已经是一个有效的URL。它跟我们解码之前的

URL非常的不同。

用Java正确处理URL

当你觉得自己已经拿到了URL的黑腰带(柔道中的最高级别--译者注),你将会发现仍有一些Java里特有的、URL

相关的陷阱。如果没有一个强大的心脏,你很难正确的处理URL。


不要用java.net.URLEncoder或者java.net.URLDecoder来处理整个URL

不开玩笑。这些类不是用来编码或解码URL的,API文档中清楚的写着:

Utility class for HTML form encoding. This class contains static methods for converting a String

 to theapplication/x-www-form-urlencodedMIME format. For more information about HTML 

form encoding, consult the HTML specification.

这不是给URL用的。充其量它类似于查询 部分的编码方式。使用它来编码或解码整个URL是错误的。你肯定以

为标准的JDK一定会有一个标准的类来正确的处理URL编码(是这样,只不过是各部分分开处理的),但是要么是

压根没有,要么是我们还没有发现。不过,这种臆测导致许多人错了URLEncoder。


在对每一部分编码之前不要拼装URL

正如我们已经讲过的:完整构建后的URL不能再被编码。

以下面的代码为例:

1String pathSegment = "a/b?c";
2String url = "http://example.com/" + pathSegment;

如果"a/b?c" 是一个路径片段,那么不可能把"http://example.com/a/b?c" 转换回之前它的原样,因为它碰

巧是一个有效的URL。之前我们已经解释过这一点。

下面是正确的代码:

1String pathSegment = "a/b?c";
2String url = "http://example.com/"
3            + URLUtils.encodePathSegment(pathSegment);

这里我们使用了一个工具类URLUtils,它是我们自己开发的,因为网络上找不到一个详尽的足够快的工具类。

上面的代码会带给你正确编码的URL "http://example.com/a%2Fb%3Fc"。

注意,同样的方式也适用于查询子串:

1String value = "a&b==c";
2String url = "http://example.com/?query=" + value;

这会给你"http://example.com/?query=a&b==c",这是个有效的URL,而不是我们想得到的

"http://example.com/?query=a%26b==c"。


不要期望 URI.getPath() 给你结构化的数据

因为一旦一个URL被解码,句法信息就会丢失,下面这样的代码就是错误的:

1URI uri = new URI("http://example.com/a%2Fb%3Fc");
2for(String pathSegment : uri.getPath().split("/"))
3  System.err.println(pathSegment);

它会先将路径 "a%2Fb%3Fc"解码为 "a/b?c",然后在不应该分割的地方将地址分割为地址片段。

正确的代码使用的是 未解码的路径 :

1URI uri = new URI("http://example.com/a%2Fb%3Fc");
2 
3for(String pathSegment : uri.getRawPath().split("/"))
4  System.err.println(URLUtils.decodePathSegment(pathSegment));

注意路径参数仍然存在:如果需要的话再处理它们。


不要期望 Apache Commons HTTPClient的URI类能够正确的做对

Apache Commons HTTPClient 3的 URI 类使用了Apache Commons Codec的URLCodec来做 URL

编码, 正如 API文档提到的 它是有问题的,因为它犯了和使用java.net.URLEncoder同样的错误。它不但

使用了错误的编码器,还错误的 按照每一部分都具有同样的预定设置进行解码。

在web应用的每一层修复URL编码问题

近来我们已经被动修复了许多应用中的URL编码问题。从在Java中支持它,到低层次的URL重写。这里我们

会列出一些必要的修改。

总是在创建的时候进行URL编码

在我们的 HTML文件中,我们将所有出现:

1var url = "#{vl:encodeURL(contextPath + '/view/' + resource.name)}";

的地方替换为:

1var url = "#{contextPath}/view/#{vl:encodeURLPathSegment(resource.name)}";

查询参数也是类似的。



酷毙
1

雷人

鲜花

鸡蛋

漂亮

刚表态过的朋友 (1 人)

  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部