冒号“ :”对于友好的 URL 使用是否安全?

我们正在设计一个 URL 系统,它将应用程序部分指定为由斜杠分隔的单词。具体来说,这是在 GWT 中,因此 URL 的相关部分将在 hash 中(这将由客户端的控制器层解释) :

http://site/gwturl#section1/section2

有些部分可能需要额外的属性,我们希望使用 :指定这些属性,以便 URL 的部分是明确的。代码首先在 /上分裂,然后在 :上分裂,像这样:

http://site/gwturl#user:45/comments

当然,我们这样做是为了网址友好性,所以我们希望确保这些具有特殊含义的字符不会被浏览器或任何其他系统对网址进行编码,并最终得到这样一个网址:

http://site/gwturl#user%3A45/comments <--- BAD

在浏览器、书签系统、甚至是 Javascript 或 Java 代码中使用冒号 安全(我的意思是不会被自动编码)吗?

116385 次浏览

我不会指望它。它可能会得到的网址编码为 %3A的许多用户代理。

来自 URLEncoder javadoc:

有关 HTML 表单的详细信息,请参阅 编码,请参考 HTML 规格

编码字符串时,如下所示 规则适用:

  • 字母数字字符“ a” 从“ z”到“ A”到“ Z”再到“0” 到“9”保持不变。
  • 那个 特殊字符“。”、“-”、“ *”和 “ _”保持不变。
  • 空间 字符“”被转换为加号 签署「 + 」。
  • 其他角色都是 不安全的,并首先转换为 使用某种编码的一个或多个字节 然后表示每个字节 3个字符的字符串“% xy”,其中 Xy 是两位十六进制 字节的表示形式 建议使用的编码方案是 但是,为了兼容性 原因,如果编码不是 指定,然后使用默认编码 的平台。

也就是说,:不安全。

结肠不安全 看这里

我没有看到 Firefox 或 IE8编码一些包含这个字符的 Wikipedia 网址

它不是一个安全字符,用于区分域名之后连接的端口

我最近 写的的一个 URL 编码器,所以这是相当新鲜的在我的脑海中。

http://site/gwturl#user:45/comments

碎片(user:45/comments)中的所有字符对于 RFC 3986 URI 都是完全合法的。

ABNF的有关部分:

fragment      = *( pchar / "/" / "?" )
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded   = "%" HEXDIG HEXDIG
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="

除了这些限制之外,片段部分没有定义超出应用程序给它的结构的结构


编辑:

噢!

尽管我断言了 URI 规范,但 声名狼藉他指出HTML 4规范限制元素名称/标识符时提供了正确的答案。

注意,标识符规则是 更改 HTML 5。URI 限制仍然适用(在撰写本文时,HTML 5使用 URI 还有一些未解决的问题)。

如果协议需要身份验证,冒号用作用户名和密码之间的分隔符。

除了 McDowell 对 URI 标准的分析之外,还要记住片段必须是有效的 HTML 锚名称。根据 http://www.w3.org/TR/html4/types.html#type-name

ID 和 NAME 标记必须以 字母([ A-Za-z ]) 任意数量的字母、数字 ([0-9]) ,连字符(“-”) ,下划线 (“ _”)、冒号(“ :”)和句号 (".").

所以你很幸运。”:”是明确允许的。任何人都不应该“%”-转义它,不仅因为“%”在那里是非法的 char,而且因为片段必须一个字符一个字符地匹配锚名,因此任何代理都不应该尝试以任何方式篡改它们。

不管你怎么测试。Web 标准没有得到严格遵守,有时候这些标准是相互冲突的。例如 HTTP/1.1 RFC 2616不允许在请求 URL 中使用查询字符串,而 HTML 在使用 GET 方法提交表单时构造一个查询字符串。在现实世界中实现的任何一个最终都会获胜。

MediaWiki 和其他 wiki 引擎在 URL 中使用冒号来指定名称空间,显然没有什么大问题。

例如 http://en.wikipedia.org/wiki/Template:Welcome

谷歌也使用冒号。

本规格中,它们使用冒号作为自定义方法名。

ApacheURIBuilder和 JAX-RSUriBuilder类对待 :的方式不同(它们对待花括号的方式也不同)

new URIBuilder("http://localhost").setCustomQuery("foo=a:b&bar={}").buildString()

输出

http://localhost?foo=a:b&bar=%7B%7D
UriBuilder.fromPath("http://localhost").queryParam("foo", "a:b").queryParam("bar", "{}").toTemplate()

输出

http://localhost?foo=a%3Ab&bar={}

因此,Apache URIBuilder 似乎并不编码 :,而是编码 {},对于 JAX-RS UriBuilder 来说,正好相反。