上週在處理一件 IIS 問題時意外發現這個詭異的設定,他讓我的網站透過 Response.Redirect 轉向時無論如何都會轉到固定網址,讓我的程式行為大亂,還好大叔我有練過 (天啊, 我變大叔了),透過 adsutil.vbs 查詢出一個十分詭異 SetHostName 屬性,這個難得的經驗當然要好好記錄一下。
我先描述一下我當時的問題,假設當時我瀏覽的網站網址為 http://www.example.com/
而我出問題的程式碼很簡單,一個簡單的網址轉向(HTTP Redirect)
Response.Redirect("/default.aspx");
然而,這一行程式照理說從 HTTP Response 標頭回傳所對應的 Header 當然是:
Location: http://www.example.com/default.aspx
但是我當時收到的 HTTP Response Header 卻是:
Location: http://www.abc.com/default.aspx
根本與我瀏覽時所連結的網址完全不同,但是我同樣的程式在任何其他 IIS 主機都沒有這個問題啊!
我找了一些時間,最後透過 adsutil.vbs 管理指令碼工具查出了以下異樣的參數(再次聲明,當 IT 不只要有腦袋,眼力也不能太差,除了要會察言觀色,還要能觀察入裡 ^^ )
備註: 假設這裡顯示的 SetHostName 為 www.abc.com
這個 SetHostName 並不會顯示在 IIS6 的 GUI 管理介面中,所以不會使用 adsutil.vbs 管理指令碼的人基本上肯定很挫折了!(難道又要重灌?)
最後我的解決方式就是將這個屬性(Property)刪除,如下指令(注意: 1603528565 為 站台識別元)
cscript adsutil.vbs delete w3svc/1603528565/SetHostName
如果要手動設定 SetHostName 的話可以用以下指令
cscript adsutil.vbs set w3svc/1603528565/SetHostName "www.example.com"
以上是 IIS6 的設定方式,到了 IIS7 的年代已經不再使用 Metabase 了,而是改用 applicationHost.config 設定檔,但你也可以使用 appcmd 進行設定。
若要自行指定 HostName 在 IIS7 可以輸入以下指令 (針對所有站台的預設值設定):
appcmd.exe set config -section:system.webServer/serverRuntime /alternateHostName:"www.example.com" /commit:apphost
也可以針對特定站台 (Default Web Site) 設定 alternateHostName 參數:
appcmd.exe set config "Default Web Site" -section:system.webServer/serverRuntime /alternateHostName:"www.example.com" /commit:apphost
你可會納悶為什麼要設定 SetHostName 或 alternateHostName 呢,這也是有點歷史因素的,主要是有些資安方面的考量,避免主機名稱或內部 IP 暴露到外面,有興趣研究的人可以參考這篇文章。
最後,透過 SetHostName 或 alternateHostName 的在寫程式方面有幾個要注意的地方:
- 所有 ASP.NET 程式收到的 Request.Url.Host 將永遠會是 SetHostName 或 alternateHostName 的值!
- 所有 Response.Redirect 若用相對路徑時,都會被轉向到 SetHostName 或 alternateHostName 設定的 HostName
- 如果你用 Request.Headers["Host"] 取得到的值才會是 Client 端送來的 HostName
相關連結