![](/img/trans.png)
[英]Why does this TransactionScope not block subsequent requests until the first request is done?
[英]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。 細節並不重要,但有兩個位:
這是問題所在:
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
。 AbsoluteUri
與眾不同。 在第二個請求中,它有兩個正斜杠。 Application.Request.ServerVariables["URL"] = /quotes/gc/v12/CMX Application.Request.ServerVariables["CACHE_URL"] = http://example.com:80/%2ffoo/baz/bar
打開問題
iisreset
之后應用程序發出的第一個請求 請記住,此問題的物理影響很小:因為它是一個實際問題,從客戶端向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.