【问题标题】:Server.UrlEncode vs. HttpUtility.UrlEncodeServer.UrlEncode 与 HttpUtility.UrlEncode
【发布时间】:2010-10-10 19:11:22
【问题描述】:

Server.UrlEncode 和 HttpUtility.UrlEncode 有区别吗?

【问题讨论】:

    标签: asp.net .net urlencode


    【解决方案1】:

    我以前对这些方法感到非常头疼,我建议您避免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 - 这东西实在是难以理解。它编码:

    • " " ==> "%20"
    • "100% true" ==> "100%%20true"(好的,您的网址现在已损坏)
    • "test A.aspx#anchor B" ==> "test%20A.aspx#anchor%20B"
    • "test A.aspx?hmm#anchor B" ==> "test%20A.aspx?hmm#anchor B"(注意与前面转义序列的区别!)

    它还有可爱的特定 MSDN 文档“编码 URL 字符串的路径部分,以实现从 Web 服务器到客户端的可靠 HTTP 传输。” - 没有实际解释它的作用。你不太可能用 Uzi 开枪打自己的脚......

    简而言之,坚持Uri.EscapeDataString

    【讨论】:

    • 不幸的是,当对某些 Web 服务器执行 HTTP 请求时,这仍然不起作用—— Uri.EscapeDataString() 不编码“!”或“'”,这与大多数浏览器实现 escape() 的工作方式不同......
    • !和 ' 字符不应该被编码;但是如果一个有问题的网络服务器需要这个,很容易解决。避免使用 javascript 的转义功能 - 它本质上是错误的(不可能往返,例如)。请参阅xkr.us/articles/javascript/encode-compare - 但简而言之;您可以改用 encodeUriComponent() ,它的行为类似于 EscapeDataString - 它可预测且可逆地编码字符串,并且也不编码!和 ' 字符。
    • 这是旧的,但问题被撞到了首页,所以.... url 字符串的路径部分是域和 ?或 # 在网址中。
    • @Tim:可能有几个?,谁说哪些要编码,哪些用作分隔符?至于空间:在这两种情况下,空间都在散列中,因此查询片段的存在与否无关紧要。最后,破坏 Uri 是不可原谅的,就像第二个包含 % 的示例一样。 UrlPathEncode 方法很简单,永远不应该使用。
    • 我认为我在stackoverflow.com/a/13993486/237091 的回答可能会对 UrlEncode/UrlPathEncode 的预期用途有所了解。
    【解决方案2】:

    HttpServerUtility.UrlEncode 将在内部使用HttpUtility.UrlEncode。没有具体的区别。 Server.UrlEncode 存在的原因是为了兼容经典的 ASP。

    【讨论】:

    【解决方案3】:

    自从第一次提出这个问题已经快 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 个字符的字符串上抛出 UriFormatExceptionWebUtility.UrlEncode 没有。 (A more common problem than you might think, particularly when dealing with URL-encoded form data.)
    • Uri.EscapeDataStringhigh surrogate characters 上抛出一个UriFormatExceptionWebUtility.UrlEncode 没有。 (这是 UTF-16 的东西,可能不太常见。)

    出于 URL 编码的目的,字符属于 3 类之一:无保留(在 URL 中是合法的);保留(合法但具有特殊含义,因此您可能想要对其进行编码);以及其他所有内容(必须始终进行编码)。

    根据RFC,保留字符为::/?#[]@!$&'()*+,;=

    并且未保留的字符是字母数字和-._~

    判决

    Uri.EscapeDataString 明确定义了它的使命:%-编码所有保留和非法字符。 WebUtility.UrlEncode 在定义和实现上都比较模糊。奇怪的是,它编码了一些保留字符而不编码其他字符(为什么是括号而不是括号??),更奇怪的是,它仍然编码了那个无辜的未保留的 ~ 字符。

    因此,我同意流行的建议 - 尽可能使用 Uri.EscapeDataString,并了解保留字符(如 /?)将被编码。如果您需要处理可能较大的字符串,尤其是 URL 编码的表单内容,您需要退回到 WebUtility.UrlEncode 并接受它的怪癖,或者以其他方式解决问题。


    编辑:我已经attempted 纠正了上面提到的Flurl 中的所有怪癖,通过Url.EncodeUrl.EncodeIllegalCharactersUrl.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}");
    

    【讨论】:

    • 这太棒了!
    • 在现代 .net 框架上验证建议的解决方案做得很好。
    • 需要说明的是,WebUtilityHttpUtility是有一些区别的。 WebUtility 使用大写字母,HttpUtility 使用小写字母表示六进制实体。此外,HttpUtility 未包含在 .NET Framework“客户端配置文件”的旧子集版本中。 WebUtility 可从 .NET Framework 4.0 获得。
    • .NET 使用WebUtility.UrlEncodeUri.EscapeDataStringUri.EscapeUriStringHttpUtility.UrlPathEncode:dotnetfiddle.net/Bo51qR 对上述代码进行修改
    • 至少从 .NET 4.8 开始(不确定引入更改的位置/时间),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+ 相同)
    【解决方案4】:

    请记住,您可能不应该使用其中任何一种方法。 Microsoft 的Anti-Cross Site Scripting Library 包括对HttpUtility.UrlEncodeHttpUtility.HtmlEncode 的替换,它们更符合标准且更安全。作为奖励,您还可以获得一个JavaScriptEncode 方法。

    【讨论】:

    • 在阅读了提供的链接上的文档和常见问题解答后,我相信这个答案是编码数据的最佳和最安全的方法!非常感谢分享这个!
    • 链接失效了。替换方法有哪些?
    • @EdwardBrey 这是最新版本的反跨站脚本库:microsoft.com/en-au/download/details.aspx?id=28589
    • 请在您的答案中包含答案。断开的链接不是很有帮助。我认为您是在暗示System.Web.Security.AntiXss.AntiXssEncoder.UrlEncode,这是另一种编码方法。
    • @SudhanshuMishra 你的链接也变成了断链......
    【解决方案5】:

    Server.UrlEncode() 用于提供与经典 ASP 的向后兼容性,

    Server.UrlEncode(str);
    

    相当于:

    HttpUtility.UrlEncode(str, Response.ContentEncoding);
    

    【讨论】:

      【解决方案6】:

      同样,Server.UrlEncode() 调用 HttpUtility.UrlEncode()

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多