﻿# 如何讓 IIS6 與 IIS7 強迫 ASP.NET 收到指定的 Host 標頭

上週在處理一件 IIS 問題時意外發現這個詭異的設定，他讓我的網站透過 Response.Redirect 轉向時無論如何都會轉到固定網址，讓我的程式行為大亂，還好大叔我有練過 (天啊, 我變大叔了)，透過 [adsutil.vbs](http://technet.microsoft.com/zh-tw/library/cc781546\(WS.10\).aspx) 查詢出一個十分詭異 **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](http://technet.microsoft.com/zh-tw/library/cc781546\(WS.10\).aspx) 管理指令碼工具查出了以下異樣的參數（再次聲明，當 IT 不只要有腦袋，眼力也不能太差，除了要會察言觀色，還要能觀察入裡 ^^ ）

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/71fff5e397a32297b145-image.png) 

備註: 假設這裡顯示的 **SetHostName** 為 **www.abc.com**

這個 SetHostName 並不會顯示在 IIS6 的 GUI 管理介面中，所以不會使用 [adsutil.vbs](http://technet.microsoft.com/zh-tw/library/cc781546\(WS.10\).aspx) 管理指令碼的人基本上肯定很挫折了！（難道又要重灌?）

最後我的解決方式就是將這個屬性(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 暴露到外面，有興趣研究的人可以參考[這篇文章](http://blogs.msdn.com/webtopics/archive/2008/11/18/removing-an-iis-server-s-ip-address-from-http-responses.aspx)。

最後，透過 SetHostName 或 alternateHostName 的在寫程式方面有幾個要注意的地方：

-   所有 ASP.NET 程式收到的 **Request.Url.Host** 將永遠會是 SetHostName 或 alternateHostName  的值!
-   所有 **Response.Redirect** 若用相對路徑時，都會被轉向到 SetHostName 或 alternateHostName 設定的 HostName
-   如果你用 **Request.Headers\["Host"\]** 取得到的值才會是 Client 端送來的 HostName

**相關連結**

-   [Server Runtime <serverRuntime>](http://www.iis.net/ConfigReference/system.webServer/serverRuntime)
-   [Removing an IIS server's IP address from HTTP responses](http://blogs.msdn.com/webtopics/archive/2008/11/18/removing-an-iis-server-s-ip-address-from-http-responses.aspx)
-   [IIS7 – Prevent the server sending its private IP address for a request made by HTTP/1.0 clients with no host header](http://blogs.msdn.com/rakkimk/archive/2008/06/07/iis7-prevent-the-server-sending-its-private-ip-address-for-a-request-made-by-http-1-0-clients-with-no-host-header.aspx)
-   [使用 Adsutil.vbs 管理指令碼](http://technet.microsoft.com/zh-tw/library/cc781546\(WS.10\).aspx)
