簡體   English   中英

IIS在第一個請求中對URL中的雙重編碼正斜杠的處理方式與后續請求的處理方式不同

[英]IIS treats double-encoded forward slashes in URLs differently on the first request than it does on subsequent requests

最近,我的團隊被要求為ASP.NET MVC應用程序實現一個HttpModule,該應用程序處理IIS 7和.NET 3.5上的雙重編碼URL。 這是問題的症結所在:

我們有時會得到具有雙重編碼正斜杠的URL,如下所示:

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

還有其他格式我們必須處理,但它們都有一些共同點,它們有一個雙重編碼的正斜杠。

為了解決這個問題,我們編寫了一個HttpModule,它僅在URL具有雙重編碼的正斜杠時起作用,並且我們將其重定向到一個合理的URL。 細節並不重要,但有兩個位:

  1. 我們無法控制這些URL具有雙重編碼正斜杠的事實
  2. 我們還沒有對.NET 4.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):

public class ForwardSlashHttpModule : IHttpModule
{
    internal IHttpApplication Application { get; set; }

    public void Dispose()
    {
        Application = null;
    }

    public void Init(HttpApplication context)
    {
        Initialize(new HttpApplicationAdapter(context));
    }

    internal void Initialize(IHttpApplication context)
    {
        Application = context;
        context.BeginRequest += context_BeginRequest;
    }

    internal void context_BeginRequest(object sender, EventArgs e)
    {
        var url = Application.Request.Url.AbsolutePath; //<-- Problem point
        //Do stuff with Url here.
    }
}

然后,在localhost上調用相同的URL:

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

注意:確保在context_BeginRequest的行之前插入Debugger.Launch()調用,以便在IIS啟動時能夠看到它

當您執行第一個請求時,您應該看到:

http://example.com/bar/foo

在后續請求中,您應該看到:

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

我的問題是:這是IIS中的錯誤嗎? 為什么在第一次調用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 

唯一有趣的是Application.Request.RawUrl發出單個編碼的正斜杠( %2f ),並將編碼的反斜杠( %5c )轉換為forwardslash(盡管其他所有內容也是如此)。

RawUrl仍然在第一個請求上進行了部分編碼。

第二個請求
Application.Request.ServerVariables["URL"] = /quotes/gc/v12/CMX
Application.Request.ServerVariables["CACHE_URL"] = http://example.com:80/%2ffoo/baz/bar

第二個請求的有趣點:

  • IsWellFormedOriginalString()false 在第一次請求時它是true
  • RawUrl是相同的(可能有用)。
  • AbsoluteUri與眾不同。 在第二個請求中,它有兩個正斜杠。

更新

 Application.Request.ServerVariables["URL"] = /quotes/gc/v12/CMX Application.Request.ServerVariables["CACHE_URL"] = http://example.com:80/%2ffoo/baz/bar 

打開問題

  • 這似乎是IIS或.NET中的錯誤。 是嗎?
  • 這僅適用於iisreset之后應用程序發出的第一個請求
  • 除了使用RawUrl之外(如果我們解析Raw Url而不是使用.NET提供的'安全'URL)我們還要擔心很多其他問題,還有什么其他方法可以解決這個問題?

請記住,此問題的物理影響很小:因為它是一個實際問題,從客戶端向Web服務器的第一個請求必須是針對上述特定URL,並且發生這種情況的可能性相對較低。

Request.Url已經可以被解碼 - 我不相信它你正在做的事情。

請參閱以下內部詳細信息: 使用url編碼的&符號的Querystring在Request.Url中過早解碼

解決方案是直接通過Request.RawUrl訪問值。

我意識到你的問題與路徑有關,但似乎正在發生同樣的事情。 試試RawUrl - 看看它是否適合你。

這真的不是一個答案,但可能是朝着正確方向邁出的一步。 我沒有時間創建測試工具來證明任何事情。

我遵循this.PrivateAbsolutePath通過Reflector,它繼續。 訪問時會有很多字符串操作。

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;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM