您好,登錄后才能下訂單哦!
這篇文章給大家介紹ASP.NET中怎么實現(xiàn)Windows身份認證,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
要使用Windows身份認證模式,需要在web.config設(shè)置:
<authentication mode="Windows" />
Windows身份認證做為ASP.NET的默認認證方式,與Forms身份認證在許多基礎(chǔ)方面是一樣的。 上篇博客我說過:我認為ASP.NET的身份認證的最核心部分其實就是HttpContext.User這個屬性所指向的對象。 在接下來的部分,我將著重分析這個對象在二種身份認證中有什么差別。
在ASP.NET身份認證過程中,IPrincipal和IIdentity這二個接口有著非常重要的作用。前者定義用戶對象的基本功能,后者定義標識對象的基本功能,不同的身份認證方式得到的這二個接口的實例也是不同的。
ASP.NET Windows身份認證是由WindowsAuthenticationModule實現(xiàn)的。 WindowsAuthenticationModule在ASP.NET管線的AuthenticateRequest事件中,使用從IIS傳遞到ASP.NET的Windows訪問令牌(Token)創(chuàng)建一個WindowsIdentity對象,Token通過調(diào)用context.WorkerRequest.GetUserToken()獲得,然后再根據(jù)WindowsIdentity 對象創(chuàng)建WindowsPrincipal對象,然后把它賦值給HttpContext.User。
在Forms身份認證中,我們需要創(chuàng)建登錄頁面,讓用戶提交用戶名和密碼,然后檢查用戶名和密碼的正確性,接下來創(chuàng)建一個包含F(xiàn)ormsAuthenticationTicket對象的登錄Cookie供后續(xù)請求使用。 FormsAuthenticationModule在ASP.NET管線的AuthenticateRequest事件中,解析登錄Cookie并創(chuàng)建一個包含F(xiàn)ormsIdentity的GenericPrincipal對象,然后把它賦值給HttpContext.User。
上面二段話簡單了概括了二種身份認證方式的工作方式。
我們可以發(fā)現(xiàn)它們存在以下差別:
1. Forms身份認證需要Cookie表示登錄狀態(tài),Windows身份認證則依賴于IIS
2. Windows身份認證不需要我們設(shè)計登錄頁面,不用編寫登錄驗證邏輯,因此更容易使用。
在授權(quán)階段,UrlAuthorizationModule仍然會根據(jù)當前用戶檢查將要訪問的資源是否得到許可。接下來,F(xiàn)ileAuthorizationModule檢查 HttpContext.User.Identity 屬性中的 IIdentity 對象是否是 WindowsIdentity 類的一個實例。如果 IIdentity 對象不是 WindowsIdentity 類的一個實例,則 FileAuthorizationModule 類停止處理。如果存在 WindowsIdentity 類的一個實例,則 FileAuthorizationModule 類調(diào)用 AccessCheck Win32 函數(shù)(通過 P/Invoke)來確定是否授權(quán)經(jīng)過身份驗證的客戶端訪問請求的文件。如果該文件的安全描述符的隨機訪問控制列表 (DACL) 中至少包含一個 Read 訪問控制項 (ACE),則允許該請求繼續(xù)。否則,F(xiàn)ileAuthorizationModule 類調(diào)用 HttpApplication.CompleteRequest 方法并將狀態(tài)碼 401 返回到客戶端。
在Windows身份認證中,驗證工作主要是由IIS實現(xiàn)的,WindowsAuthenticationModule其實只是負責創(chuàng)建WindowsPrincipal和WindowsIdentity而已。順便介紹一下:Windows 身份驗證又分為“NTLM 身份驗證”和“Kerberos v5 身份驗證”二種,關(guān)于這二種Windows身份認證的更多說明可查看MSDN技術(shù)文章:解釋:ASP.NET 2.0 中的 Windows 身份驗證。在我看來,IIS最終使用哪種Windows身份認證方式并不影響我們的開發(fā)過程,因此本文不會討論這個話題。
根據(jù)我的實際經(jīng)驗來看,使用Windows身份認證時,主要的開發(fā)工作將是根據(jù)登錄名從Active Directory獲取用戶信息。因為,此時不需要我們再設(shè)計登錄過程,IIS與ASP.NET已經(jīng)為我們準備好了WindowsPrincipal和WindowsIdentity這二個與用戶身份相關(guān)的對象。
訪問 Active Directory
我們通常使用LDAP協(xié)議來訪問Active Directory,在.net framework中提供了DirectoryEntry和DirectorySearcher這二個類型讓我們可以方便地從托管代碼中訪問 Active Directory 域服務(wù)。
如果我們要在"test.corp”這個域中搜索某個用戶信息,我們可以使用下面的語句構(gòu)造一個DirectoryEntry對象:
DirectoryEntry entry = new DirectoryEntry("LDAP://test.corp");
在這段代碼中,我采用硬編碼的方式把域名寫進了代碼。
我們?nèi)绾沃喇斍半娔X所使用的是哪個域名呢?
答案是:查看“我的電腦”的屬性對話框:
注意:這個域名不一定與System.Environment.UserDomainName相同。
除了可以查看“我的電腦”的屬性對話框外,我們還可以使用代碼的方式獲取當前電腦所使用的域名:
private static string GetDomainName() { // 注意:這段代碼需要在Windows XP及較新版本的操作系統(tǒng)中才能正常運行。 SelectQuery query = new SelectQuery("Win32_ComputerSystem"); using( ManagementObjectSearcher searcher = new ManagementObjectSearcher(query) ) { foreach( ManagementObject mo in searcher.Get() ) { if( (bool)mo["partofdomain"] ) return mo["domain"].ToString(); } } return null; }
當構(gòu)造了DirectorySearcher對象后,我們便可以使用DirectorySearcher來執(zhí)行對Active Directory的搜索。
我們可以使用下面的步驟來執(zhí)行搜索:
1. 設(shè)置 DirectorySearcher.Filter 指示LDAP格式篩選器,這是一個字符串。
2. 多次調(diào)用PropertiesToLoad.Add() 設(shè)置搜索過程中要檢索的屬性列表。
3. 調(diào)用FindOne() 方法獲取搜索結(jié)果。
下面的代碼演示了如何從Active Directory中搜索登錄名為“fl45”的用戶信息:
static void Main(string[] args) { Console.WriteLine(Environment.UserDomainName); Console.WriteLine(Environment.UserName); Console.WriteLine("------------------------------------------------"); ShowUserInfo("fl45", GetDomainName()); } private static string AllProperties = "name,givenName,samaccountname,mail"; public static void ShowUserInfo(string loginName, string domainName) { if( string.IsNullOrEmpty(loginName) || string.IsNullOrEmpty(domainName) ) return; string[] properties = AllProperties.Split(new char[] { '\r', '\n', ',' }, StringSplitOptions.RemoveEmptyEntries); try { DirectoryEntry entry = new DirectoryEntry("LDAP://" + domainName); DirectorySearcher search = new DirectorySearcher(entry); search.Filter = "(samaccountname=" + loginName + ")"; foreach( string p in properties ) search.PropertiesToLoad.Add(p); SearchResult result = search.FindOne(); if( result != null ) { foreach( string p in properties ) { ResultPropertyValueCollection collection = result.Properties[p]; for( int i = 0; i < collection.Count; i++ ) Console.WriteLine(p + ": " + collection[i]); } } } catch( Exception ex ) { Console.WriteLine(ex.ToString()); } }
結(jié)果如下:
在前面的代碼,我在搜索Active Directory時,只搜索了"name,givenName,samaccountname,mail"這4個屬性。然而,LDAP還支持更多的屬性,我們可以使用下面的代碼查看更多的用戶信息:
private static string AllProperties = @" homemdb distinguishedname countrycode cn lastlogoff mailnickname dscorepropagationdata msexchhomeservername msexchmailboxsecuritydescriptor msexchalobjectversion usncreated objectguid whenchanged memberof msexchuseraccountcontrol accountexpires displayname primarygroupid badpwdcount objectclass instancetype objectcategory samaccounttype whencreated lastlogon useraccountcontrol physicaldeliveryofficename samaccountname usercertificate givenname mail userparameters adspath homemta msexchmailboxguid pwdlastset logoncount codepage name usnchanged legacyexchangedn proxyaddresses department userprincipalname badpasswordtime objectsid sn mdbusedefaults telephonenumber showinaddressbook msexchpoliciesincluded textencodedoraddress lastlogontimestamp company ";
在ASP.NET中訪問Active Directory
前面我在一個控制臺程序中演示了訪問Active Directory的方法,通過示例我們可以看到:在代碼中,我用Environment.UserName就可以得到當前用戶的登錄名。然而,如果是在ASP.NET程序中,訪問Environment.UserName就很有可能得不到真正用戶登錄名。因為:Environment.UserName是使用WIN32API中的GetUserName獲取線程相關(guān)的用戶名,但ASP.NET運行在IIS中,線程相關(guān)的用戶名就不一定是客戶端的用戶名了。不過,ASP.NET可以模擬用戶方式運行,通過這種方式才可以得到正確的結(jié)果。關(guān)于“模擬”的話題在本文的后面部分有說明。
在ASP.NET中,為了能可靠的獲取登錄用戶的登錄名,我們可以使用下面的代碼:
/// <summary> /// 根據(jù)指定的HttpContext對象,獲取登錄名。 /// </summary> /// <param name="context"></param> /// <returns></returns> public static string GetUserLoginName(HttpContext context) { if( context == null ) return null; if( context.Request.IsAuthenticated == false ) return null; string userName = context.User.Identity.Name; // 此時userName的格式為:UserDomainName\LoginName // 我們只需要后面的LoginName就可以了。 string[] array = userName.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); if( array.Length == 2 ) return array[1]; return null; }
在ASP.NET中使用Windows身份認證時,IIS和WindowsAuthenticationModule已經(jīng)做了許多驗證用戶的相關(guān)工作,雖然我們可以使用前面的代碼獲取到用戶的登錄名,但用戶的其它信息即需要我們自己來獲取。在實際使用Windows身份認證時,我們要做的事:基本上就是從Active Directory中根據(jù)用戶的登錄名獲取所需的各種信息。
比如:我的程序在運行時,還需要使用以下與用戶相關(guān)的信息:
public sealed class UserInfo { public string GivenName; public string FullName; public string Email; }
那么,我們可以使用這樣的代碼來獲取所需的用戶信息:
public static class UserHelper { /// <summary> /// 活動目錄中的搜索路徑,也可根據(jù)實際情況來修改這個值。 /// </summary> public static string DirectoryPath = "LDAP://" + GetDomainName(); /// <summary> /// 獲取與指定HttpContext相關(guān)的用戶信息 /// </summary> /// <param name="context"></param> /// <returns></returns> public static UserInfo GetCurrentUserInfo(HttpContext context) { string loginName = GetUserLoginName(context); if( string.IsNullOrEmpty(loginName) ) return null; return GetUserInfoByLoginName(loginName); } /// <summary> /// 根據(jù)指定的HttpContext對象,獲取登錄名。 /// </summary> /// <param name="context"></param> /// <returns></returns> public static string GetUserLoginName(HttpContext context) { if( context == null ) return null; if( context.Request.IsAuthenticated == false ) return null; string userName = context.User.Identity.Name; // 此時userName的格式為:UserDomainName\LoginName // 我們只需要后面的LoginName就可以了。 string[] array = userName.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); if( array.Length == 2 ) return array[1]; return null; } /// <summary> /// 根據(jù)登錄名查詢活動目錄,獲取用戶信息。 /// </summary> /// <param name="loginName"></param> /// <returns></returns> public static UserInfo GetUserInfoByLoginName(string loginName) { if( string.IsNullOrEmpty(loginName) ) return null; // 下面的代碼將根據(jù)登錄名查詢用戶在AD中的信息。 // 為了提高性能,可以在此處增加一個緩存容器(Dictionary or Hashtable)。 try { DirectoryEntry entry = new DirectoryEntry(DirectoryPath); DirectorySearcher search = new DirectorySearcher(entry); search.Filter = "(SAMAccountName=" + loginName + ")"; search.PropertiesToLoad.Add("givenName"); search.PropertiesToLoad.Add("cn"); search.PropertiesToLoad.Add("mail"); // 如果還需要從AD中獲取其它的用戶信息,請參考ActiveDirectoryDEMO SearchResult result = search.FindOne(); if( result != null ) { UserInfo info = new UserInfo(); info.GivenName = result.Properties["givenName"][0].ToString(); info.FullName = result.Properties["cn"][0].ToString(); info.Email = result.Properties["mail"][0].ToString(); return info; } } catch { // 如果需要記錄異常,請在此處添加代碼。 } return null; } private static string GetDomainName() { // 注意:這段代碼需要在Windows XP及較新版本的操作系統(tǒng)中才能正常運行。 SelectQuery query = new SelectQuery("Win32_ComputerSystem"); using( ManagementObjectSearcher searcher = new ManagementObjectSearcher(query) ) { foreach( ManagementObject mo in searcher.Get() ) { if( (bool)mo["partofdomain"] ) return mo["domain"].ToString(); } } return null; } }
使用UserHelper的頁面代碼:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>WindowsAuthentication DEMO - http://www.cnblogs.com/fish-li/</title> </head> <body> <% if( Request.IsAuthenticated ) { %> 當前登錄全名:<%= Context.User.Identity.Name.HtmlEncode()%> <br /> <% var user = UserHelper.GetCurrentUserInfo(Context); %> <% if( user != null ) { %> 用戶短名:<%= user.GivenName.HtmlEncode()%> <br /> 用戶全名:<%= user.FullName.HtmlEncode() %> <br /> 郵箱地址:<%= user.Email.HtmlEncode() %> <% } %> <% } else { %> 當前用戶還未登錄。 <% } %> </body> </html>
程序運行的效果如下:
另外,還可以從Active Directory查詢一個叫做memberof的屬性(它與Windows用戶組無關(guān)),有時候可以用它區(qū)分用戶,設(shè)計與權(quán)限相關(guān)的操作。
在設(shè)計數(shù)據(jù)持久化的表結(jié)構(gòu)時,由于此時沒有“用戶表”,那么我們可以直接保存用戶的登錄名。剩下的開發(fā)工作就與Forms身份認證沒有太多的差別了。
使用Active Directory驗證用戶身份
前面介紹了ASP.NET Windows身份認證,在這種方式下,IIS和WindowsAuthenticationModule為我們實現(xiàn)了用戶身份認證的過程。然而,有時可能由于各種原因,需要我們以編程的方式使用Active Directory驗證用戶身份,比如:在WinForm程序,或者其它的驗證邏輯。
我們不僅可以從Active Directory中查詢用戶信息,也可以用它來實現(xiàn)驗證用戶身份,這樣便可以實現(xiàn)自己的登錄驗證邏輯。
不管是如何使用Active Directory,我們都需要使用DirectoryEntry和DirectorySearcher這二個對象。 DirectoryEntry還提供一個構(gòu)造函數(shù)可讓我們輸入用戶名和密碼:
// 摘要: // 初始化 System.DirectoryServices.DirectoryEntry 類的新實例。 // // 參數(shù): // Password: // 在對客戶端進行身份驗證時使用的密碼。DirectoryEntry.Password 屬性初始化為該值。 // // username: // 在對客戶端進行身份驗證時使用的用戶名。DirectoryEntry.Username 屬性初始化為該值。 // // Path: // 此 DirectoryEntry 的路徑。DirectoryEntry.Path 屬性初始化為該值。 public DirectoryEntry(string path, string username, string password);
要實現(xiàn)自己的登錄檢查,就需要使用這個構(gòu)造函數(shù)。以下是我寫用WinForm寫的一個登錄檢查的示例:
private void btnLogin_Click(object sender, EventArgs e) { if( txtUsername.Text.Length == 0 || txtPassword.Text.Length == 0 ) { MessageBox.Show("用戶名或者密碼不能為空。", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } string ldapPath = "LDAP://" + GetDomainName(); string domainAndUsername = Environment.UserDomainName + "\\" + txtUsername.Text; DirectoryEntry entry = new DirectoryEntry(ldapPath, domainAndUsername, txtPassword.Text); DirectorySearcher search = new DirectorySearcher(entry); try { SearchResult result = search.FindOne(); MessageBox.Show("登錄成功。", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information); } catch( Exception ex ) { // 如果用戶名或者密碼不正確,也會拋出異常。 MessageBox.Show(ex.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Stop); } }
程序運行的效果如下:
安全上下文與用戶模擬
在ASP.NET Windows身份認證環(huán)境中,與用戶相關(guān)的安全上下文對象保存在HttpContext.User屬性中,是一個類型為WindowsPrincipal的對象,我們還可以訪問HttpContext.User.Identity來獲取經(jīng)過身份認證的用戶標識,它是一個WindowsIdentity類型的對象。
在.NET Framework中,我們可以通過WindowsIdentity.GetCurrent()獲取與當前線程相關(guān)的WindowsIdentity對象,這種方法獲取的是當前運行的Win32線程的安全上下文標識。由于ASP.NET運行在IIS進程中,因此ASP.NET線程的安全標識其實是從IIS的進程中繼承的,所以此時用二種方法得到的WindowsIdentity對象其實是不同的。
在Windows操作系統(tǒng)中,許多權(quán)限檢查都是基于Win32線程的安全上下文標識,于是前面所說的二種WindowsIdentity對象會造成編程模型的不一致問題,為了解決這個問題,ASP.NET提供了“模擬”功能,允許線程以特定的Windows帳戶的安全上下文來訪問資源。
為了能更好的理解模擬的功能,我準備了一個示例(ShowWindowsIdentity.ashx):
public class ShowWindowsIdentity : IHttpHandler { public void ProcessRequest (HttpContext context) { // 要觀察【模擬】的影響, // 可以啟用,禁止web.config中的設(shè)置:<identity impersonate="true"/> context.Response.ContentType = "text/plain"; context.Response.Write(Environment.UserDomainName + "\\" + Environment.UserName + "\r\n"); WindowsPrincipal winPrincipal = (WindowsPrincipal)HttpContext.Current.User; context.Response.Write(string.Format("HttpContext.Current.User.Identity: {0}, {1}\r\n", winPrincipal.Identity.AuthenticationType, winPrincipal.Identity.Name)); WindowsPrincipal winPrincipal2 = (WindowsPrincipal)Thread.CurrentPrincipal; context.Response.Write(string.Format("Thread.CurrentPrincipal.Identity: {0}, {1}\r\n", winPrincipal2.Identity.AuthenticationType, winPrincipal2.Identity.Name)); WindowsIdentity winId = WindowsIdentity.GetCurrent(); context.Response.Write(string.Format("WindowsIdentity.GetCurrent(): {0}, {1}", winId.AuthenticationType, winId.Name)); }
首先,在web.config中設(shè)置:
<authentication mode="Windows" />
注意:要把網(wǎng)站部署在IIS中,否則看不出效果。
此時,訪問ShowWindowsIdentity.ashx,將看到如下圖所示的結(jié)果:
現(xiàn)在修改一下web.config中設(shè)置:(注意:后面加了一句配置)
<authentication mode="Windows" /> <identity impersonate="true"/>
此時,訪問ShowWindowsIdentity.ashx,將看到如下圖所示的結(jié)果:
說明:
1. FISH-SRV2003是我的計算機名。它在一個沒有域的環(huán)境中。
2. fish-li是我的一個Windows帳號的登錄名。
3. 網(wǎng)站部署在IIS6中,進程以NETWORK SERVICE帳號運行。
4. 打開網(wǎng)頁時,我輸入的用戶名是fish-li
前面二張圖片的差異之處其實也就是ASP.NET的“模擬”所發(fā)揮的功能。
關(guān)于模擬,我想說四點:
1. 在ASP.NET中,我們應(yīng)該訪問HttpContext.User.Identity獲取當前用戶標識,那么就不存在問題(此時可以不需要模擬),例如FileAuthorizationModule就是這樣處理的。
2. 模擬只是在ASP.NET應(yīng)用程序訪問Windows系統(tǒng)資源時需要應(yīng)用Windows的安全檢查功能才會有用。
3. Forms身份認證也能配置模擬功能,但只能模擬一個Windows帳戶。
4. 絕大多數(shù)情況下是不需要模擬的。
在IIS中配置Windows身份認證
與使用Forms身份認證的程序不同,使用Windows身份認證的程序需要額外的配置步驟。這個小節(jié)將主要介紹在IIS中配置Windows身份認證,我將常用的IIS6和IIS7.5為例分別介紹這些配置。
IIS6的配置 請參考下圖:
IIS7.5的配置 請參考下圖:
注意:Windows身份認證是需要安裝的,方法請參考下圖:
關(guān)于瀏覽器的登錄對話框問題
當我們用瀏覽器訪問一個使用Windows身份認證的網(wǎng)站時,瀏覽器都會彈出一個對話框(左IE,右Safari):
此時,要求我們輸入Windows的登錄帳號,然后交給IIS驗證身份。
首次彈出這個對話框很正常:因為程序要驗證用戶的身份。
然而,每次關(guān)閉瀏覽器下次重新打開頁面時,又會出現(xiàn)此對話框,此時感覺就很不方便了。
雖然有些瀏覽器能記住用戶名和密碼,但我發(fā)現(xiàn)FireFox,Opera,Chrome仍然會彈出這個對話框,等待我們點擊確定,只有Safari才不會打擾用戶直接打開網(wǎng)頁。 IE的那個“記住我的密碼”復(fù)選框完全是個擺設(shè),它根本不會記住密碼!
因此,我所試過的所有瀏覽器中,只有Safari是最人性化的。
雖然在默認情況下,雖然IE不會記住密碼,每次都需要再次輸入。
不過,IE卻可以支持不提示用戶輸入登錄帳號而直接打開網(wǎng)頁, 此時IE將使用用戶的當前Windows登錄帳號傳遞給IIS驗證身份。
要讓IE打開一個Windows身份認證的網(wǎng)站不提示登錄對話框,必須滿足以下條件:
1. 必須在 IIS 的 Web 站點屬性中啟用 Windows 集成身份驗證。
2. 客戶端和Web服務(wù)器都必須在基于Microsoft Windows的同一個域內(nèi)。
3. Internet Explorer 必須把所請求的 URL 視為 Intranet(本地)。
4. Internet Explorer 的 Intranet 區(qū)域的安全性設(shè)置必須設(shè)為“只在 Intranet 區(qū)域自動登錄”。
5. 請求Web頁的用戶必須具有訪問該Web頁以及該Web頁中引用的所有對象的適當?shù)奈募到y(tǒng)(NTFS)權(quán)限。
6. 用戶必須用域帳號登錄到Windows 。
在這幾個條件中,如果網(wǎng)站是在一個Windows域中運行,除了第3條可能不滿足外,其它條件應(yīng)該都容易滿足(第4條是默認值)。因此,要讓IE不提示輸入登錄帳號,只要確保第3條滿足就可以了。下面的圖片演示了如何完成這個配置:(注意:配置方法也適合用域名訪問的情況)
另外,除了在IE中設(shè)置Intranet外,還可以在訪問網(wǎng)站時,用計算機名代替IP地址或者域名,那么IE始終認為是在訪問Intranet內(nèi)的網(wǎng)站,此時也不會彈出登錄對話框。
在此,我想再啰嗦三句:
1. IE在集成Windows身份認證時,雖然不提示登錄對話框,但是不表示不安全,它會自動傳遞登錄憑據(jù)。
2. 這種行為只有IE才能支持。(其它的瀏覽器只是會記住密碼,在實現(xiàn)上其實是不一樣的。)
3. 集成Windows身份認證,也只適合在Intranet的環(huán)境中使用。
在客戶端代碼中訪問Windows身份認證的頁面
在上篇博客中,我演示了如何用代碼訪問一個使用Forms身份認證的網(wǎng)站中的受限頁面,方法是使用CookieContainer對象接收服務(wù)端生的登錄Cookie。然而,在Windows身份認證的網(wǎng)站中,身份驗證的過程發(fā)生在IIS中,而且根本不使用Cookie保存登錄狀態(tài),而是需要在請求時發(fā)送必要的身份驗證信息。
在使用代碼做為客戶端訪問Web服務(wù)器時,我們?nèi)匀恍枰褂肏ttpWebRequest對象。為了能讓HttpWebRequest在訪問IIS時發(fā)送必要的身份驗證信息,HttpWebRequest提供二個屬性都可以完成這個功能:
// 獲取或設(shè)置請求的身份驗證信息。 // // 返回結(jié)果: // 包含與該請求關(guān)聯(lián)的身份驗證憑據(jù)的 System.Net.ICredentials。默認為 null。 public override ICredentials Credentials { get; set; } // 獲取或設(shè)置一個 System.Boolean 值,該值控制默認憑據(jù)是否隨請求一起發(fā)送。 // // 返回結(jié)果: // 如果使用默認憑據(jù),則為 true;否則為 false。默認值為 false。 public override bool UseDefaultCredentials { get; set; }
下面是我準備的完整的示例代碼(注意代碼中的注釋):
static void Main(string[] args) { try { // 請把WindowsAuthWebSite1這個網(wǎng)站部署在IIS中, // 開啟Windows認證方式,并禁止匿名用戶訪問。 // 然后修改下面的訪問地址。 HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:33445/Default.aspx"); // 下面三行代碼,啟用任意一行都是可以的。 request.UseDefaultCredentials = true; //request.Credentials = CredentialCache.DefaultCredentials; //request.Credentials = CredentialCache.DefaultNetworkCredentials; // 如果上面的三行代碼全被注釋了,那么將會看到401的異常信息。 using( HttpWebResponse response = (HttpWebResponse)request.GetResponse() ) { using( StreamReader sr = new StreamReader(response.GetResponseStream()) ) { Console.WriteLine(sr.ReadToEnd()); } } } catch( WebException wex ) { Console.WriteLine("====================================="); Console.WriteLine("異常發(fā)生了。"); Console.WriteLine("====================================="); Console.WriteLine(wex.Message); } }
其實關(guān)鍵部分還是設(shè)置UseDefaultCredentials或者Credentials,代碼中的三種方法是有效的。
這三種方法的差別:
1. Credentials = CredentialCache.DefaultCredentials; 表示在發(fā)送請求會帶上當前用戶的身份驗證憑據(jù)。
2. UseDefaultCredentials = true; 此方法在內(nèi)部會調(diào)用前面的方法,因此與前面的方法是一樣的。
3. Credentials = CredentialCache.DefaultNetworkCredentials; 是在.NET 2.0中引用的新方法。
關(guān)于DefaultCredentials和DefaultNetworkCredentials的更多差別,請看我整理的表格:
Credentials屬性 | 申明類型 | 實例類型 | .NET支持版本 |
DefaultCredentials | ICredentials | SystemNetworkCredential | 從1.0開始 |
DefaultNetworkCredentials | NetworkCredential | SystemNetworkCredential | 從2.0開始 |
三個類型的繼承關(guān)系:
1. NetworkCredential實現(xiàn)了ICredentials接口,
2. SystemNetworkCredential繼承自NetworkCredential。
關(guān)于ASP.NET中怎么實現(xiàn)Windows身份認證就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。