【发布时间】:2010-10-10 19:11:22
【问题描述】:
Server.UrlEncode 和 HttpUtility.UrlEncode 有区别吗?
【问题讨论】:
Server.UrlEncode 和 HttpUtility.UrlEncode 有区别吗?
【问题讨论】:
我以前对这些方法感到非常头疼,我建议您避免UrlEncode 的任何变体,而是使用Uri.EscapeDataString - 至少那个有可理解的行为。
让我们看看...
HttpUtility.UrlEncode(" ") == "+" //breaks ASP.NET when used in paths, non-
//standard, undocumented.
Uri.EscapeUriString("a?b=e") == "a?b=e" // makes sense, but rarely what you
// want, since you still need to
// escape special characters yourself
但我个人最喜欢的一定是 HttpUtility.UrlPathEncode - 这东西实在是难以理解。它编码:
它还有可爱的特定 MSDN 文档“编码 URL 字符串的路径部分,以实现从 Web 服务器到客户端的可靠 HTTP 传输。” - 没有实际解释它的作用。你不太可能用 Uzi 开枪打自己的脚......
简而言之,坚持Uri.EscapeDataString。
【讨论】:
?,谁说哪些要编码,哪些用作分隔符?至于空间:在这两种情况下,空间都在散列中,因此查询片段的存在与否无关紧要。最后,破坏 Uri 是不可原谅的,就像第二个包含 % 的示例一样。 UrlPathEncode 方法很简单,永远不应该使用。
HttpServerUtility.UrlEncode 将在内部使用HttpUtility.UrlEncode。没有具体的区别。 Server.UrlEncode 存在的原因是为了兼容经典的 ASP。
【讨论】:
自从第一次提出这个问题已经快 9 年了,在 .NET Core 和 .NET Standard 的世界中,我们对 URL 编码最常见的选项似乎是 WebUtility.UrlEncode(在System.Net 下)和Uri.EscapeDataString。从这里和其他地方最流行的答案来看,Uri.EscapeDataString 似乎更可取。但是是吗?我做了一些分析以了解差异,这就是我想出的:
WebUtility.UrlEncode 将空间编码为+; Uri.EscapeDataString 将其编码为 %20。Uri.EscapeDataString 百分比编码 !、(、) 和 *; WebUtility.UrlEncode 没有。WebUtility.UrlEncode 百分比编码 ~; Uri.EscapeDataString 没有。Uri.EscapeDataString 在超过 65,520 个字符的字符串上抛出 UriFormatException; WebUtility.UrlEncode 没有。 (A more common problem than you might think, particularly when dealing with URL-encoded form data.)Uri.EscapeDataString 在high surrogate characters 上抛出一个UriFormatException; WebUtility.UrlEncode 没有。 (这是 UTF-16 的东西,可能不太常见。)出于 URL 编码的目的,字符属于 3 类之一:无保留(在 URL 中是合法的);保留(合法但具有特殊含义,因此您可能想要对其进行编码);以及其他所有内容(必须始终进行编码)。
根据RFC,保留字符为::/?#[]@!$&'()*+,;=
并且未保留的字符是字母数字和-._~
Uri.EscapeDataString 明确定义了它的使命:%-编码所有保留和非法字符。 WebUtility.UrlEncode 在定义和实现上都比较模糊。奇怪的是,它编码了一些保留字符而不编码其他字符(为什么是括号而不是括号??),更奇怪的是,它仍然编码了那个无辜的未保留的 ~ 字符。
因此,我同意流行的建议 - 尽可能使用 Uri.EscapeDataString,并了解保留字符(如 / 和 ?)将被编码。如果您需要处理可能较大的字符串,尤其是 URL 编码的表单内容,您需要退回到 WebUtility.UrlEncode 并接受它的怪癖,或者以其他方式解决问题。
编辑:我已经attempted 纠正了上面提到的Flurl 中的所有怪癖,通过Url.Encode、Url.EncodeIllegalCharacters 和Url.Decode 静态方法。这些在core package 中(很小,不包括所有的HTTP 内容),或者随意从源头撕掉它们。我欢迎您对这些提供任何 cmets/反馈。
这是我用来发现哪些字符编码不同的代码:
var diffs =
from i in Enumerable.Range(0, char.MaxValue + 1)
let c = (char)i
where !char.IsHighSurrogate(c)
let diff = new {
Original = c,
UrlEncode = WebUtility.UrlEncode(c.ToString()),
EscapeDataString = Uri.EscapeDataString(c.ToString()),
}
where diff.UrlEncode != diff.EscapeDataString
select diff;
foreach (var diff in diffs)
Console.WriteLine($"{diff.Original}\t{diff.UrlEncode}\t{diff.EscapeDataString}");
【讨论】:
WebUtility.UrlEncode、Uri.EscapeDataString、Uri.EscapeUriString 和HttpUtility.UrlPathEncode:dotnetfiddle.net/Bo51qR 对上述代码进行修改
Uri.EscapeDataString("?") 将正确编码为 4 个 UTF-8 八位字节,表明此方法当前是 Unicode-outside- of-BMP 安全。此外,MSDN now documents the maximum input length as 32k, not 64k(.NET Framework 4.8 和 .NET Core+ 相同)
请记住,您可能不应该使用其中任何一种方法。 Microsoft 的Anti-Cross Site Scripting Library 包括对HttpUtility.UrlEncode 和HttpUtility.HtmlEncode 的替换,它们更符合标准且更安全。作为奖励,您还可以获得一个JavaScriptEncode 方法。
【讨论】:
System.Web.Security.AntiXss.AntiXssEncoder.UrlEncode,这是另一种编码方法。
Server.UrlEncode() 用于提供与经典 ASP 的向后兼容性,
Server.UrlEncode(str);
相当于:
HttpUtility.UrlEncode(str, Response.ContentEncoding);
【讨论】:
同样,Server.UrlEncode() 调用 HttpUtility.UrlEncode()
【讨论】: