URL中的URL编码斜杠

时间:2009-02-26 17:58:57

标签: c# asp.net-mvc asp.net-mvc-routing urlencode

我的地图是:

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

如果我使用网址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));
    }
}

EDIT1:

最后,事实证明最好的方法是为我需要选择的每个项目保存一个格式良好的字符串。这更好,因为现在我只编码值,从不解码它们。所有特殊字符都变为“ - ”。我的很多db-table现在都有这个额外的列“URL”。数据非常稳定,这就是我可以这样做的原因。如果“URL”中的数据是唯一的,我甚至可以检查。

EDIT2:

还要注意空间特征。它在VS集成网络服务器上看起来不错,但在iis7 Properly url encode space character

上有所不同

10 个答案:

答案 0 :(得分:47)

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

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

答案 1 :(得分:24)

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

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

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

这会导致Uri类根据描述URI的RFC行为,允许在路径中转义斜杠而不进行非转义。出于安全原因,CLR团队报告他们偏离了规范,并且在.config文件中设置此内容基本上使您获得了所有其他安全性考虑因素的所有权,而不是取消斜杠。

答案 2 :(得分:21)

以下是对解决方案的简单解释以及对已经说过的内容的总结。

请求方:

  1. UrlEncode your path。
  2. 将'%'替换为'!'。
  3. 提出请求。
  4. 回应方:

    1. 替换'!' '%'。
    2. Url解码您的路径。
    3. 按预期使用参数。
    4. 冲洗,重复,享受。

答案 3 :(得分:11)

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

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

答案 4 :(得分:9)

Java / Tomcat也一样。

如果您的网址中包含编码的“/”(%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中的路径分隔符(两个选项   默认为false):

     
      
  • 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无效的URI:noSlash”

您可以在Tomcat启动脚本中切换错误修复:

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

答案 5 :(得分:1)

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

答案 6 :(得分:0)

这对.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);
    }

答案 7 :(得分:0)

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

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

答案 8 :(得分:-1)

根据Symfony 1.x开发人员遇到的问题(here中建议+),建议PHP comments for urlencode()

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

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

优点:

  • 避免需要额外的转义过程(如果用'!'或'_'等特殊字符替换'/')
  • 不依赖于任何服务器设置,例如Apache的AllowEncodedSlashes

答案 9 :(得分:-3)

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