URL 中的 URL 编码斜杠

Posted

技术标签:

【中文标题】URL 中的 URL 编码斜杠【英文标题】:URL-encoded slash in URL 【发布时间】:2010-10-10 03:40:47 【问题描述】:

我的地图是:

routes.MapRoute(
   "Default",                                             // Route name
   "controller/action/id",                          // URL with params
   new  controller = "Home", action = "Index", id = ""  // Param defaults
);

如果我使用 URL http://localhost:5000/Home/About/100%2f200,则没有匹配的路由。 我将 URL 更改为 http://localhost:5000/Home/About/100 然后再次匹配路由。

是否有任何简单的方法来处理包含斜杠的参数?其他转义值(空格%20)似乎也有效。

编辑:

对 Base64 进行编码对我有用。它使 URL 变得丑陋,但现在没关系。

public class UrlEncoder
 
    public string URLDecode(string  decode)
    
        if (decode == null) return null;
        if (decode.StartsWith("="))
        
            return FromBase64(decode.TrimStart('='));
        
        else
        
            return HttpUtility.UrlDecode( decode) ;
        
    

    public string UrlEncode(string encode)
    
        if (encode == null) return null;
        string encoded = HttpUtility.PathEncode(encode);
        if (encoded.Replace("%20", "") == encode.Replace(" ", ""))
        
            return encoded;
        
        else
        
            return "=" + ToBase64(encode);
        
    

    public string ToBase64(string encode)
    
        Byte[] btByteArray = null;
        UTF8Encoding encoding = new UTF8Encoding();
        btByteArray = encoding.GetBytes(encode);
        string sResult = System.Convert.ToBase64String(btByteArray, 0, btByteArray.Length);
        sResult = sResult.Replace("+", "-").Replace("/", "_");
        return sResult;
    

    public string FromBase64(string decode)
    
        decode = decode.Replace("-", "+").Replace("_", "/");
        UTF8Encoding encoding = new UTF8Encoding();
        return encoding.GetString(Convert.FromBase64String(decode));
    

编辑1:

最后发现,最好的方法是为我需要选择的每个项目保存一个格式良好的字符串。那好多了,因为现在我只编码值而从不解码它们。所有特殊字符变为“-”。我的很多数据库表现在都有这个附加列“URL”。数据很稳定,所以我可以走这条路。我什至可以检查“URL”中的数据是否唯一。

编辑2:

还要注意空格字符。在 VS 集成网络服务器上看起来不错,但在 iis7 Properly url encode space character 上有所不同

【问题讨论】:

Gath Adams 建议对任何可以包含斜杠的参数进行 Base64 编码。他还更详细地解释了这个问题:博客条目:gathadams.com/2009/01/06/… 您还可以想出一些其他方法来掩盖斜线,例如,按照惯例将其替换为其他内容。我知道。这也很丑陋,但至少 URL 保持可读性。 我注意到正斜杠和点会给我错误。我做了一个快速助手,用“-slash-”和“-dot-”替换它们。想知道为什么常规的 Url.Encode/Decode 不能解决问题。另外,为什么转义字符会出错? 哇,伙伴! Base64 编码也包括斜线字符!这不是您可以依赖的解决方案。 这不是路由的编码问题;这显然是 .NET Uri 类中的一个错误。根据 [我对 URI RFC 的阅读],路径中的编码斜杠不应被视为段分隔符。 MVC 路由没有机会正确处理它,因为 Uri 类(错误地)在路由甚至看到斜杠之前就对其进行解码。请参阅 RFC 的第 2.2 和 2.4 节。 labs.apache.org/webarch/uri/rfc/rfc3986.html#reserved 【参考方案1】:

如果它只是你的最后一个参数,你可以这样做:

routes.MapRoute(
    "Default",                                                // Route name
    "controller/action/*id",                            // URL with parameters
    new  controller = "Home", action = "Index", id = "" );  // Parameter defaults

【讨论】:

我不习惯将这种做法作为一般做法,尤其是在面向公众的网站上,但我确实在 Intranet webapp 上这样做过,并且对此并不感到内疚。感谢您指出这个解决方案! @jkade(或任何人)为什么在面向公众的网站上对此不满意? 对于那些只希望它用于单个路由的人,您可以通过 RouteAttribute 对控制器的操作执行相同的操作,例如[路线(“*id”)] 这实际上对 %5C 没有任何帮助【参考方案2】:

这里是对解决方案的简单解释和已经说过的总结。

请求方:

    UrlEncode 您的路径。 将 '%' 替换为 '!'。 提出请求。

响应方:

    替换“!”带有“%”。 UrlDecode 您的路径。 按预期使用参数。

冲洗,重复,享受。

【讨论】:

您可能和我一样也遇到这个问题:应用程序错误:此请求的 URL 长度超过了配置的 maxUrlLength 值。可以通过添加这个 web.config 值来解决: 简单有效!谢谢。 更好地编写自己的网络服务器【参考方案3】:

在 .NET 4.0 beta 2 中,CLR 团队提供了一种解决方法。

将此添加到您的 web.config 文件中:

<uri> 
    <schemeSettings>
        <add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
    </schemeSettings>
</uri>

这会导致 Uri 类根据 RFC 描述 URI 的行为,允许在路径中转义斜杠而不进行转义。 CLR 团队报告说,出于安全原因,他们偏离了规范,并且在您的 .config 文件中进行设置基本上可以让您掌握不转义斜杠所涉及的其他安全考虑因素。

【讨论】:

这听起来很棒。一旦 .NET 4.0 发布,我将使用它作为答案。 这不起作用。你在 Visual Studio 中得到蓝色下划线,它似乎没有效果。 注意:在 .NET 4 的正式版本中,MSDN 声明此设置只能添加到 machine.config 或 application.config - 而不是 web.config。 多年以后,.NET Framework 4.7.1 和 Uri 类仍然存在问题。很多。这对我来说是一个非常模糊的行为。请注意,对于类库项目,不会出现此问题。 @StephenLloyd 这在 web.config 中对我有用(使用 .NET Framework 经典 4.7.1 的 ASP.NET 应用程序)。【参考方案4】:

另一种选择是使用查询字符串值。很蹩脚,但比自定义编码简单。

http://localhost:5000/Home/About?100%2f200

【讨论】:

好电话,乔恩。这是我能想到的唯一安全的方法。它有点打破惯例,但是当您的 ID 必须是任何字符的字符串时,它解决了问题。 我不认为这是蹩脚的 - 我认为这是最好的选择 - 我认为你的例子是错误的吗?应该是 - /About?x=100%2f200 - no??【参考方案5】:

Java / Tomcat 也是如此。

如果您的 URL 中有编码的“/” (%2F),仍然存在问题。

RFC 3986 - 第 2.2 节说:“如果 URI 组件的数据与保留字符作为分隔符的用途发生冲突,则冲突数据必须在 URI 形成之前进行百分比编码。” (RFC 3986 - 第 2.2 节)

但是Tomcat有一个问题:

http://tomcat.apache.org/security-6.html - 在 Apache Tomcat 6.0.10 中已修复

重要:目录遍历 CVE-2007-0450

Tomcat 允许“\”、“%2F”和“%5C” [...]。

以下 Java 系统属性 已添加到 Tomcat 以提供 对处理的附加控制 URL 中的路径分隔符(两个选项 默认为假):

org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH: 真|假 org.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH: 真|假

由于无法保证 所有 URL 都由 Tomcat 处理为 他们在代理服务器,Tomcat 应始终保持安全,就好像没有 限制上下文访问的代理是 用过。

影响:6.0.0-6.0.9

所以如果你有一个带有 %2F 字符的 URL,Tomcat 会返回:“400 Invalid URI: noSlash”

您可以在Tomcat启动脚本中切换bugfix:

set JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG%   -Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true 

【讨论】:

【参考方案6】:

您可以避免上述双重编码/解码建议,只需使用 HttpServerUtility.UrlTokenEncode 和相应的 UrlTokenDecode。

【讨论】:

【参考方案7】:

关于 .NET 4 很有趣。无论如何,此链接描述了 RFC 1738 并包括哪些字符需要编码,哪些只是“不安全”。 link text

如果我想要一个 SEO 友好的 URL(例如当您想在 URL 中放置论坛帖子主题时),则跳过编码并替换任何不是 A-Z、a-z、0-9 的内容。

public static string CreateSubjectSEO(string str)
    
        int ci;
        char[] arr = str.ToCharArray();
        for (int i = 0; i < arr.Length; i++)
        
            ci = Convert.ToInt32(arr[i]);
            if (!((ci > 47 && ci < 58) || (ci > 64 && ci < 91) || (ci > 96 && ci < 123)))
            
                arr[i] = '-';
            
        
        return new string(arr);
    

【讨论】:

【参考方案8】:

对于入站编码的“/”问题,我可以通过将“*”添加到所有 id 参数来解决我的问题,然后能够正确地将编码的“/”传递到控件中(参数是一个字符串带有编码的“/”)

routes.MapRoute(
            name: "Default",
            url: "controller/action/*id",
            defaults: new 
             
                controller = "Control", 
                action = "Action", 
                id = UrlParameter.Optional 
            )

【讨论】:

【参考方案9】:

当 Symfony 1.x 开发人员遇到问题时,正如 here 建议的那样(+ 在 php comments for urlencode() 中建议):

urlencode() 之前将“/”编码为“%2F” 在(如有必要)urldecode() 之后将“%2F”解码为“/”

注意:您可以使用rawurlencode(),但您仍需要对 '/' 进行两次 urlencode。

优点:

无需额外的转义过程(如果将“/”替换为“!”或“_”等特殊字符) 不要依赖任何服务器设置,例如 Apache 的 AllowEncodedSlashes

【讨论】:

这不适用于 ASP.NET 4。它仍然显示 HTTP Error 400 - Bad Request。 抱歉,如果此答案适用于 PHP/Apache。我想同样的逻辑应该适用于 ASP.NET。也许有人会在我之前有时间为 ASP.NET “翻译”它。我留下我的答案,因为我认为它可以提供帮助,即使使用的技术不同(如 @simonox 答案)【参考方案10】:

只需使用Server.UrlDecode。它会起作用,我已经测试过了。

【讨论】:

UrlDecoding 不是这里的问题,它是 MVC 中的路由,并且带有斜杠 (%2f) 的编码字符串将在路由中被解析,就好像它们是 (%2f) 的一部分一样网址。

以上是关于URL 中的 URL 编码斜杠的主要内容,如果未能解决你的问题,请参考以下文章

url 编码的正斜杠破坏了我的 codeigniter 应用程序

需要在 Apache 上允许编码斜杠

AS3将正斜杠转换为URL编码字符%2F

SQL注入防御绕过——二次编码之干掉反斜杠

什么是URL编码和URL解码

如何在 Elastic Beanstalk 负载均衡器环境中允许编码斜杠