問題簡介
每當遇到http錯誤碼為400,代表用戶端發起的請求不符合伺服器對請求的某些限制,或者請求本身存在一定的錯誤。
目前400錯誤經常出現在使用者認證階段,當一個使用者從屬於過多的域時,在Kerberos認證階段會將域資訊發送給伺服器,從而導致請求欄位長度超過伺服器設定的上限。
問題重現
更改註冊表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\http\Parameters
MaxFieldLength = 10 (hex) 通過以下命令重起系統http服務 (需要管理員權限)
Net stop http
Net start http 通過以下命令重起iis服務
IISRESET 通過瀏覽器訪問伺服器網頁
調試方法
400錯誤產生自http層級,伺服器端http.sys檢測到任何與其配置不符合的請求會直接回複400錯誤給用戶端,同時在C:\Windows\System32\LogFiles\HTTPERR\httperr.log檔案中記錄日誌表明失敗原因。
Http error log
#Software:Microsoft HTTP API 2.0
#Version:1.0
#Date:2012-09-05 05:01:22
#Fields:date time c-ip c-port s-ip s-port cs-version cs-method cs-uri sc-statuss-siteid s-reason s-queuename
2012-09-0505:01:22 ::1%0 20567 ::1%0 80 HTTP/1.1 GET / 400 - FieldLength
也可以通過IE Developer Tool來追蹤傳回碼。
開啟IE, 按F12開啟Developer Tool
在network選項卡上點擊StartCapture按鈕
瀏覽網頁,查看返回碼
解決方案
方案一
減少請求中發送的欄位長度,使其符合伺服器規定。如果該問題是因為該使用者加入了過多域組,那就要從一些組中退出來以減少請求長度。
方案二
更改伺服器設定,在註冊表中更改MaxFieldLength和MaxRequestBytes設定的大小。
具體應該設為多大呢。
可以根據這個連結提供的方式計算token的大小http://support.microsoft.com/kb/327825
然後把MaxFieldLength和MaxRequestBytes的大小設定為token大小的4/3。
如果不想計算,可以安裝一個fiddler在用戶端,清IE cache,然後發送一個請求然後查看統計資訊。一共發送了多少位元組可以通過以下方式來查看。
方案三
改用NTLM取代Kerberos認證方式,這樣域組資訊不會被發送,但是這要根據實際環境需求而定,如果需要用到Kerberos delegation功能,肯定不能改為NTLM。另外Kerberos相對NTLM是一種更為安全的認證方式,所以該方案在選擇的時候要更加謹慎。
下面這個連結有對http.sys中相應的登錄機碼的詳細介紹,可以通過它來查看windows可以通過那些配置來控制http協議層的行為。
Http.sysregistrysettingsforIIS
http://support.microsoft.com/kb/820129/en-us
參考文檔
http://support.microsoft.com/kb/2020943
http://support.microsoft.com/kb/820129/en-us
http://support.microsoft.com/kb/327825