2008-08-31

.NET 1.1 WebRequest KeepAlive 和 WebProxy.Credentials 的奇怪現象

發生在一個 .NET 1.1 的 App 上的問題, 簡化後的程式碼如下:

HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.KeepAlive = false;

request.Proxy = new WebProxy(proxyServer);
request.Proxy.Credentials = new NetworkCredential(userName, password);

HttpWebResponse response = request.GetResponse() as HttpWebResponse;
response.Close();

因為某種原因, 在一開始時刻意將 KeepAlive 屬性設為 false, 導致了這個奇怪現象的發生, 而且只會在 .NET 1.1 底下發生! 症狀是如果 KeepAlive 設為 false 的話, 就會丟出 407 Proxy Authentication Required 的例外, 可是同樣的程式在自家的環境內卻又測不出問題, 所以初步研判應該是 Proxy server 不同的原因所造成, 如果是在 Microsoft ISA Server 的環境中就會發生, 而在 Squid Proxy Server 則沒有這個問題, 這是什麼道理咧?!

道理說穿了很簡單, 因為 Squid Proxy Server 是採用 Basic 的驗證方式, 而 ISA Server 預設卻是 challenge-response 的驗證機制, Basic 的驗證方式是將帳號密碼以 base64 的方式編碼傳送出去, 所以和 server 不需要保持連線, 但是 challenge-response 則必需要保持連線才可以進行驗證, 這就是為什麼當 HttpWebRequest 的 KeepAlive 設成 false 的時候, 在 ISA Server 的環境一直驗證失敗的原因! 而 .NET 2.0 之所以不會發生這個問題是因為有針對這個情況做特別處理, 也就是在進行 challenge-response 驗證時, 會自動將 Proxy-Connection 的 Header 設為 Keep-Alive, 待驗證過後才再設為 Close, 所以不會出問題!

相關知識可以參考 Authentication in WinHttp, Challenge-response authentication 和一篇寫的很詳細的 blog 文章 WebProxy.Credentials does not work when KeepAlive = false in .NET 1.1

keywords: httpwebrequest, proxy, credentials, keepalive

沒有留言: