CSharp Tips:應用程序訪問集成Windows認證的站點

問題
從事過Web Application的人都知道,在一個Web Site可以允許用戶匿名訪問,也可以禁止匿名強制要求認證才能夠訪問。
在IIS的Directory Property/Directory Security下可以看到匿名訪問(Anonymous access)和認證訪問(Authenticated access)的選項。在認證訪問中又有多種方式:基本認證(Basic)、摘要認證(Digest),還有著名的Windows集成(Integrated Windows authentication,以前應該叫做Challenge/Response)。
當選擇和認證訪問的時候,如果沒有經過認證,任何請求都會被服務器拒絕,返回401-Unauthenticated的錯誤。通過IE訪問Web Site,瀏覽器會幫你做掉很多事情,特別是當選擇Windows集成模式,而用戶又是登錄域的,對用戶感覺完全透明。但是在應用程序中怎麼才能夠向一個要求認證訪問的站點發送請求呢?這就是我們的問題所在。
 
原因
在DotNet下面我們通常採用System.Web.HttpWebRequest/HttpWebResponse來完成有關HTTP的操作,對於客戶端來說比較重要的就是發送請求的HttpWebRequest。
普通情況下,我們創建一個請求:
   oRequest = (System.Net.HttpWebRequest) WebRequest.Create(uri);
   if (oRequest != null)
   {
    // send request
    oRequest.ProtocolVersion = HttpVersion.Version11;
    oRequest.Method = @"GET";
    oResponse = (System.Net.HttpWebResponse) oRequest.GetResponse();
    }
這段代碼請求允許匿名訪問的站點的時候沒有任何問題,但是當站點關閉匿名訪問的開關的時候,就會收到上面提到的401的錯誤。因爲我們並沒有指定訪問該站點的用戶ID。
 
解決
HttpWebRequest類中有一個屬性Credentials,該屬性就是用來存放認證信息的。
如果希望用當前登錄用戶的認證信息,可以這麼賦值:
     oRequest.Credentials = CredentialCache.DefaultCredentials;
CredentialCache.DefaultCredentials記錄了應用程序當前運行上下文中的認證信息,但是你無法從中讀取用戶名、口令和登錄域(都是空字符串),不過確確實實記錄了當前登錄用戶的信息,這也是Windows的保護機制吧。
 
如果希望用一個指定用戶的身份訪問,那麼就必須提供用戶名,口令和域名:
     oCredential = new NetworkCredential(sUser,sPwd,sDomain);
     oRequest.Credentials = oCredential.GetCredential(new Uri(uri),String.Empty);
在GetCredential方法中可以指定認證方式,也就是“Basic”、“NTLM”之類。具體參數含義,參考MSDN。
完整的例子
   oRequest = (System.Net.HttpWebRequest) WebRequest.Create(uri);
   if (oRequest != null)
   {
    // send request
    oRequest.ProtocolVersion = HttpVersion.Version11;
    oRequest.Method = @"GET";
    if (sUser != String.Empty)
    {
     oCredential = new NetworkCredential(sUser,sPwd,sDomain);
     oRequest.Credentials = oCredential.GetCredential(new Uri(uri),String.Empty);
    }
    else
    {
     oRequest.Credentials = CredentialCache.DefaultCredentials;
    }
    oResponse = (System.Net.HttpWebResponse) oRequest.GetResponse();
    }
這樣只要當前登錄用戶或者你提供帳號和口令的用戶通過任何,你就可以像普通情況下一樣訪問Web Site上的資源了。當然如果提供了錯誤的用戶名或者口令的話,不要來找我。
DotNet下非常簡單,就到這裏。
 
IE做了點什麼?
題外話,談談當訪問一個需要認證的站點的時候,IE做了點什麼。
當服務端選擇集成Windows的認證模式時,用戶通過IE請求被保護的資源,服務端返回一個401的錯誤碼,以及一個WWWW-Authenticate的HTTP報頭(Header)。IE收到這個Header之後,將當前用戶名、機器名和域名傳遞給服務端,服務端繼續迴應一個401的錯誤碼以及WWW-Authenticate的報頭。這是IE換算Password再次發送給服務端,這個時候認證纔算完成。
如果當前登錄Windows的用戶沒有權限訪問服務端的資源,IE就會彈出一個對話框,要求用戶輸入訪問用戶名、口令和域名,再次重複上述過程。如果用戶三次輸入錯誤的信息,那麼IE也玩不動了,直接告訴你“未經授權”。
可見IE還是做了很多事情的。如果我們要寫一個比較好的客戶端程序,也需要重複考慮這些問題。
 
 
參考文檔
 
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章