Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# IIS在第一个请求中对URL中的双编码前向斜杠的处理方式与在后续请求中的处理方式不同_C#_.net_Asp.net Mvc_Iis_Httpmodule - Fatal编程技术网

C# IIS在第一个请求中对URL中的双编码前向斜杠的处理方式与在后续请求中的处理方式不同

C# IIS在第一个请求中对URL中的双编码前向斜杠的处理方式与在后续请求中的处理方式不同,c#,.net,asp.net-mvc,iis,httpmodule,C#,.net,Asp.net Mvc,Iis,Httpmodule,最近,我的团队被要求为ASP.NET MVC应用程序实现一个HttpModule,该应用程序处理IIS 7和.NET 3.5上的双编码URL。问题的关键在于: 我们有时会得到带有双编码前斜杠的URL,如下所示: http://www.example.com/%252fbar%5cbaz/foo 我们还需要处理其他格式,但它们都有一些共同点,它们有一个双编码正斜杠 为了解决这个问题,我们编写了一个HttpModule,它只在URL具有双编码正斜杠时才起作用,并将其重定向到一个正常的URL。细节并

最近,我的团队被要求为ASP.NET MVC应用程序实现一个HttpModule,该应用程序处理IIS 7和.NET 3.5上的双编码URL。问题的关键在于:

我们有时会得到带有双编码前斜杠的URL,如下所示:

http://www.example.com/%252fbar%5cbaz/foo
我们还需要处理其他格式,但它们都有一些共同点,它们有一个双编码正斜杠

为了解决这个问题,我们编写了一个HttpModule,它只在URL具有双编码正斜杠时才起作用,并将其重定向到一个正常的URL。细节并不重要,但有两个方面:

  • 我们无法控制这样一个事实,即这些URL具有双编码的前斜杠
  • 而且我们还没有升级到.NET4.0,也不是马上就可以升级的
  • 问题是:

    IIS启动后的第一个请求显示与第二个请求不同的URL

    如果我们使用上述示例中的URL,则对IIS的第一个请求如下所示:

    http://www.example.com/bar/baz/foo

    第二个请求看起来像:

    http://www.example.com/%252fbar%5cbaz/foo

    这是通过在调试时检查
    Application.Request.Url.AbsolutePath
    属性来完成的

    下面是重现问题的最小代码示例(创建一个新的MVC应用程序,并注册以下HttpModule):

    注意:确保在
    context\u BeginRequest
    中的行之前插入一个
    Debugger.Launch()
    调用,以便您能够在IIS第一次启动时看到它

    执行第一个请求时,您应该看到:

    http://example.com/bar/foo

    在后续请求中,您应该看到:

    http://example.com//bar/foo

    我的问题是:这是IIS中的一个bug吗?为什么在第一次调用
    Application.Request.Url.AbsolutePath时,它会提供不同的Url,但不会为任何后续请求提供

    另外:不管第一个请求是否为双编码URL,第二个请求总是由IIS适当地处理(或者至少在处理双编码前斜杠时适当地处理)。这是第一个问题

    更新 我尝试了几个不同的属性,以查看第一个请求中是否有不同的值:

    第一个请求
    string u = Application.Request.Url.AbsoluteUri;
    "http://example.com/foo/baz/bar/"
    string x = Application.Request.Url.OriginalString;
    "http://example.com:80/foo/baz/bar"
    string y = Application.Request.RawUrl;
    "/%2ffo/baz/bar"
    bool z = Application.Request.Url.IsWellFormedOriginalString();
    true
    
    唯一有趣的是,
    应用程序.Request.RawUrl
    发出一个编码的正斜杠(
    %2f
    ),并将编码的反斜杠(
    %5c
    )转换为正斜杠(尽管其他所有操作都会这样做)

    在第一个请求中,
    RawUrl
    仍然是部分编码的

    第二个请求
    string u = Application.Request.Url.AbsoluteUri;
    "http://example.com//foo/baz/bar"
    string x = Application.Request.Url.OriginalString;
    "http://example.com:80/%2ffoo/baz/bar"
    string y = Application.Request.RawUrl;
    "/%2ffoo/baz/bar"
    bool z = Application.Request.Url.IsWellFormedOriginalString();
    false
    
    第二个请求的有趣之处:

    • IsWellFormedOriginalString()
      false
      。在第一次请求时,它是
      true
    • RawUrl是相同的(可能有帮助)
    • AbsoluteUri
      是不同的。在第二个请求中,它有两个正斜杠
    更新 开放性问题

    • 这似乎是IIS或.NET中的一个bug。是吗
    • 这仅对应用程序在
      iisreset
    • 除了使用RawUrl(如果我们解析原始Url而不是使用.NET提供的“安全”Url,我们还需要担心很多其他问题),还有什么其他方法可以处理这个问题

    请记住,此问题的物理影响很小:要使其成为实际问题,客户端向web服务器发出的第一个请求必须是上述特定URL,发生这种情况的可能性相对较低。

    这确实不是一个答案,但可能是朝着正确方向迈出的一步。我还没有时间创建一个测试工具来证明任何事情

    我通过反射器跟踪了这个.PrivateAbsolutePath
    ,它一直在继续。当它被访问时,有很多字符串操作

    public string AbsolutePath
    {
        get
        {
            if (this.IsNotAbsoluteUri)
            {
                throw new InvalidOperationException(SR.GetString("net_uri_NotAbsolute"));
            }
            string privateAbsolutePath = this.PrivateAbsolutePath; //HERE
            if (this.IsDosPath && (privateAbsolutePath[0] == '/'))
            {
                privateAbsolutePath = privateAbsolutePath.Substring(1); 
            }
            return privateAbsolutePath;
        }
    }
    

    Url已经可以解码了-我不相信你在做什么

    有关内部详细信息,请参见:

    解决方案是通过Request.RawUrl直接访问这些值


    我知道你的问题在于这条路,但似乎同样的事情正在发生。试试RawUrl-看看它是否适合您。

    好的,检查标题缓存\u URL如何?如果这是解码的,那么在你得到它的时候,它的IIS或浏览器行为就会消失。查看更多信息如果其未解码且HTTP_URL为,则其IIS进行编码。如果两者都是未编码的,那么很可能所有的asp.net.net都是这样。这不就是说如果路径以/开头,就把它切掉吗?这里没有解码。@RandomEngy这也是我问题的关键:为什么第一个请求和第二个请求有什么不同。我将看看其他答案和其他评论,并尝试那里列出的内容;但这是困扰我的一部分,行为从第一个请求变为第二个请求。除非IIS第一次处理它,并为每个后续请求将其推送到.NET(因为可能.NET仍在为第一个请求旋转?),否则它似乎不应该这样做。ASP.NET总是处理所有事情,即使是第一个请求。我的猜测是一些初始化代码直接或间接地导致了这种行为。不是,它每次都执行,但你看到的是整个类依赖的一个属性,以及很多可能每次都不起作用的东西。仔细想想这条路,你就会明白我的意思。
    string u = Application.Request.Url.AbsoluteUri;
    "http://example.com//foo/baz/bar"
    string x = Application.Request.Url.OriginalString;
    "http://example.com:80/%2ffoo/baz/bar"
    string y = Application.Request.RawUrl;
    "/%2ffoo/baz/bar"
    bool z = Application.Request.Url.IsWellFormedOriginalString();
    false
    
    Application.Request.ServerVariables["URL"] = /quotes/gc/v12/CMX
    Application.Request.ServerVariables["CACHE_URL"] = http://example.com:80/%2ffoo/baz/bar
    
    public string AbsolutePath
    {
        get
        {
            if (this.IsNotAbsoluteUri)
            {
                throw new InvalidOperationException(SR.GetString("net_uri_NotAbsolute"));
            }
            string privateAbsolutePath = this.PrivateAbsolutePath; //HERE
            if (this.IsDosPath && (privateAbsolutePath[0] == '/'))
            {
                privateAbsolutePath = privateAbsolutePath.Substring(1); 
            }
            return privateAbsolutePath;
        }
    }