IIS 是否執行非法字元替換?如果是這樣,如何阻止它?
上下文:在 IIS 中執行的 ASP.NET MVC,帶有 UTF-8 % 編碼的 URL。
使用標準項目模板和類似的測試操作
HomeController:public ActionResult Test(string id) { return Content(id, "text/plain"); }這適用於大多數 % 編碼的 UTF-8 路由,例如:
http://mydevserver/Home/Test/%e4%ba%ac%e9%83%bd%e5%bc%81與預期的結果京都弁
但是使用路線:
http://mydevserver/Home/Test/%ee%93%bb未正確接收url 。
旁白:
%ee%93%bb是 %-encoded 程式碼點 0xE4FB;基本多語言平面,私人使用區域;但最終 - 一個有效的 unicode 程式碼點;您可以手動或通過以下方式驗證這一點:string value = ((char) 0xE4FB).ToString(); string encoded = HttpUtility.UrlEncode(value); // %ee%93%bb現在,接下來會發生什麼取決於網路伺服器;在 Visual Studio 開發伺服器(又名 cassini)上,
id接收到正確的 - 長度為 1 的字元串,包含程式碼點 0xE4FB。但是,如果我在 IIS 或 IIS Express 中執行此操作,我會得到一個不同的
id,特別"î“»"是程式碼點:0xEE、0x201C、0xBB。您會立即將第一個和最後一個辨識為百分比編碼字元串的開始和結束……那麼中間發生了什麼?好吧:
在我看來,IIS 在處理我的 url 時執行了某種引用翻譯。現在也許這可能在一些場景中有用(我不知道),但是當它發生在 % 編碼的 UTF-8 塊的中間時肯定是一件壞事。
請注意,這
HttpContext.Current.Request.Raw也表明發生了這種翻譯,因此這看起來不像是 MVC 錯誤;另請注意 Darin 的評論,強調它在 url 的路徑與查詢部分中的工作方式不同。所以(兩部分):
- 我的分析是否遺漏了 unicode / url 處理的一些重要細節?
- 我如何解決它?(即讓我收到預期的字元)
最終,為了解決這個問題,我不得不使用
request.ServerVariables["HTTP_URL"]和一些手動解析,以及一堆錯誤處理備份(另外補償一些相關的故障Uri)。不是很好,但只會影響極少數尷尬的請求。
id = Encoding.UTF8.GetString(Encoding.Default.GetBytes(id));這將為您提供您的原始 ID。IIS 對路徑字元使用預設 (ANSI) 編碼。您的 url 編碼字元串是使用它解碼的,這就是為什麼您會得到一個奇怪的東西。
要獲取原始 id,您可以將其轉換回字節並使用 utf8 編碼獲取字元串。
ISAPI 過濾器是一個 ANSI API - 您可以使用 API 獲取/設置的所有值都必須是 ANSI。是的,我知道這很令人震驚;畢竟,現在是 2006 年,現在的一切都是 Unicode……但請記住,這個 API 起源於十多年前,當時幾乎沒有任何東西是 32 位的,更不用說 Unicode。另外,請記住 ISAPI 直接操作的 HTTP 協議是 ANSI 而不是 Unicode。
*編輯:*既然你提到它適用於大多數其他字元,所以我假設 IIS 有某種編碼檢測機制,在這種情況下它失敗了。作為一種解決方法,儘管您可以在您的 id 前面加上這個 char,然後您可以輕鬆檢測問題是否發生(如果這個 char 失去)。不是一個非常理想的解決方案,但它會起作用。然後,您可以在 ASP.NET MVC 中編寫您的自定義模型綁定器和一個包裝器類,以使您的消費程式碼更清晰。