精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

細(xì)說ASP.NET Windows身份認(rèn)證

開發(fā) 后端
Windows身份認(rèn)證做為ASP.NET的默認(rèn)認(rèn)證方式,與Forms身份認(rèn)證在許多基礎(chǔ)方面是一樣的。

要使用Windows身份認(rèn)證模式,需要在web.config設(shè)置:

  1. <authentication mode="Windows" /> 

Windows身份認(rèn)證做為ASP.NET的默認(rèn)認(rèn)證方式,與Forms身份認(rèn)證在許多基礎(chǔ)方面是一樣的。 上篇博客我說過:我認(rèn)為ASP.NET的身份認(rèn)證的最核心部分其實就是HttpContext.User這個屬性所指向的對象。 在接下來的部分,我將著重分析這個對象在二種身份認(rèn)證中有什么差別。

在ASP.NET身份認(rèn)證過程中,IPrincipal和IIdentity這二個接口有著非常重要的作用。前者定義用戶對象的基本功能,后者定義標(biāo)識對象的基本功能,不同的身份認(rèn)證方式得到的這二個接口的實例也是不同的。

ASP.NET Windows身份認(rèn)證是由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身份認(rèn)證中,我們需要創(chuàng)建登錄頁面,讓用戶提交用戶名和密碼,然后檢查用戶名和密碼的正確性,接下來創(chuàng)建一個包含F(xiàn)ormsAuthenticationTicket對象的登錄Cookie供后續(xù)請求使用。 FormsAuthenticationModule在ASP.NET管線的AuthenticateRequest事件中,解析登錄Cookie并創(chuàng)建一個包含F(xiàn)ormsIdentity的GenericPrincipal對象,然后把它賦值給HttpContext.User。

上面二段話簡單了概括了二種身份認(rèn)證方式的工作方式。

我們可以發(fā)現(xiàn)它們存在以下差別:

1. Forms身份認(rèn)證需要Cookie表示登錄狀態(tài),Windows身份認(rèn)證則依賴于IIS

2. Windows身份認(rèn)證不需要我們設(shè)計登錄頁面,不用編寫登錄驗證邏輯,因此更容易使用。

在授權(quán)階段,UrlAuthorizationModule仍然會根據(jù)當(dāng)前用戶檢查將要訪問的資源是否得到許可。接下來,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身份認(rèn)證中,驗證工作主要是由IIS實現(xiàn)的,WindowsAuthenticationModule其實只是負(fù)責(zé)創(chuàng)建WindowsPrincipal和WindowsIdentity而已。順便介紹一下:Windows 身份驗證又分為“NTLM 身份驗證”和“Kerberos v5 身份驗證”二種,關(guān)于這二種Windows身份認(rèn)證的更多說明可查看MSDN技術(shù)文章:解釋:ASP.NET 2.0 中的 Windows 身份驗證。在我看來,IIS最終使用哪種Windows身份認(rèn)證方式并不影響我們的開發(fā)過程,因此本文不會討論這個話題。

根據(jù)我的實際經(jīng)驗來看,使用Windows身份認(rèn)證時,主要的開發(fā)工作將是根據(jù)登錄名從Active Directory獲取用戶信息。因為,此時不需要我們再設(shè)計登錄過程,IIS與ASP.NET已經(jīng)為我們準(zhǔn)備好了WindowsPrincipal和WindowsIdentity這二個與用戶身份相關(guān)的對象。

訪問 Active Directory

我們通常使用LDAP協(xié)議來訪問Active Directory,在.net framework中提供了DirectoryEntry和DirectorySearcher這二個類型讓我們可以方便地從托管代碼中訪問 Active Directory 域服務(wù)。

如果我們要在"test.corp”這個域中搜索某個用戶信息,我們可以使用下面的語句構(gòu)造一個DirectoryEntry對象:

  1. DirectoryEntry entry = new DirectoryEntry("LDAP://test.corp"); 

在這段代碼中,我采用硬編碼的方式把域名寫進了代碼。

我們?nèi)绾沃喇?dāng)前電腦所使用的是哪個域名呢?

答案是:查看“我的電腦”的屬性對話框:

注意:這個域名不一定與System.Environment.UserDomainName相同。

除了可以查看“我的電腦”的屬性對話框外,我們還可以使用代碼的方式獲取當(dāng)前電腦所使用的域名:

  1. private static string GetDomainName()  
  2. {  
  3.     // 注意:這段代碼需要在Windows XP及較新版本的操作系統(tǒng)中才能正常運行。  
  4.     SelectQuery query = new SelectQuery("Win32_ComputerSystem");  
  5.     using( ManagementObjectSearcher searcher = new ManagementObjectSearcher(query) ) {  
  6.         foreach( ManagementObject mo in searcher.Get() ) {  
  7.             if( (bool)mo["partofdomain"] )  
  8.                 return mo["domain"].ToString();  
  9.         }  
  10.     }  
  11.     return null;  

當(dāng)構(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”的用戶信息:

  1. static void Main(string[] args)  
  2. {  
  3.     Console.WriteLine(Environment.UserDomainName);  
  4.     Console.WriteLine(Environment.UserName);  
  5.     Console.WriteLine("------------------------------------------------");  
  6.  
  7.     ShowUserInfo("fl45", GetDomainName());  
  8. }  
  9.  
  10. private static string AllProperties = "name,givenName,samaccountname,mail";  
  11.  
  12. public static void ShowUserInfo(string loginName, string domainName)  
  13. {  
  14.     ifstring.IsNullOrEmpty(loginName) || string.IsNullOrEmpty(domainName) )  
  15.         return;  
  16.  
  17.     string[] properties = AllProperties.Split(new char[] { '\r''\n'',' },   
  18.                         StringSplitOptions.RemoveEmptyEntries);  
  19.  
  20.     try {  
  21.         DirectoryEntry entry = new DirectoryEntry("LDAP://" + domainName);  
  22.         DirectorySearcher search = new DirectorySearcher(entry);  
  23.         search.Filter = "(samaccountname=" + loginName + ")";  
  24.  
  25.         foreachstring p in properties )  
  26.             search.PropertiesToLoad.Add(p);  
  27.  
  28.         SearchResult result = search.FindOne();  
  29.  
  30.         if( result != null ) {  
  31.             foreachstring p in properties ) {  
  32.                 ResultPropertyValueCollection collection = result.Properties[p];  
  33.                 forint i = 0; i < collection.Count; i++ )  
  34.                     Console.WriteLine(p + ": " + collection[i]);  
  35.             }  
  36.         }  
  37.     }  
  38.     catch( Exception ex ) {  
  39.         Console.WriteLine(ex.ToString());  
  40.     }  

結(jié)果如下:

在前面的代碼,我在搜索Active Directory時,只搜索了"name,givenName,samaccountname,mail"這4個屬性。然而,LDAP還支持更多的屬性,我們可以使用下面的代碼查看更多的用戶信息:

  1.         private static string AllProperties = @"  
  2. homemdb  
  3. distinguishedname  
  4. countrycode  
  5. cn  
  6. lastlogoff  
  7. mailnickname  
  8. dscorepropagationdata  
  9. msexchhomeservername  
  10. msexchmailboxsecuritydescriptor  
  11. msexchalobjectversion  
  12. usncreated  
  13. objectguid  
  14. whenchanged  
  15. memberof  
  16. msexchuseraccountcontrol  
  17. accountexpires  
  18. displayname  
  19. primarygroupid  
  20. badpwdcount  
  21. objectclass  
  22. instancetype  
  23. objectcategory  
  24. samaccounttype  
  25. whencreated  
  26. lastlogon  
  27. useraccountcontrol  
  28. physicaldeliveryofficename  
  29. samaccountname  
  30. usercertificate  
  31. givenname  
  32. mail  
  33. userparameters  
  34. adspath  
  35. homemta  
  36. msexchmailboxguid  
  37. pwdlastset  
  38. logoncount  
  39. codepage  
  40. name  
  41. usnchanged  
  42. legacyexchangedn  
  43. proxyaddresses  
  44. department  
  45. userprincipalname  
  46. badpasswordtime  
  47. objectsid  
  48. sn  
  49. mdbusedefaults  
  50. telephonenumber  
  51. showinaddressbook  
  52. msexchpoliciesincluded  
  53. textencodedoraddress  
  54. lastlogontimestamp  
  55. company  
  56. "; 

在ASP.NET中訪問Active Directory

前面我在一個控制臺程序中演示了訪問Active Directory的方法,通過示例我們可以看到:在代碼中,我用Environment.UserName就可以得到當(dāng)前用戶的登錄名。然而,如果是在ASP.NET程序中,訪問Environment.UserName就很有可能得不到真正用戶登錄名。因為:Environment.UserName是使用WIN32API中的GetUserName獲取線程相關(guān)的用戶名,但ASP.NET運行在IIS中,線程相關(guān)的用戶名就不一定是客戶端的用戶名了。不過,ASP.NET可以模擬用戶方式運行,通過這種方式才可以得到正確的結(jié)果。關(guān)于“模擬”的話題在本文的后面部分有說明。

在ASP.NET中,為了能可靠的獲取登錄用戶的登錄名,我們可以使用下面的代碼:

  1. /// <summary>  
  2. /// 根據(jù)指定的HttpContext對象,獲取登錄名。  
  3. /// </summary>  
  4. /// <param name="context"></param>  
  5. /// <returns></returns>  
  6. public static string GetUserLoginName(HttpContext context)  
  7. {  
  8.     if( context == null )  
  9.         return null;  
  10.  
  11.     if( context.Request.IsAuthenticated == false )  
  12.         return null;  
  13.  
  14.     string userName = context.User.Identity.Name;  
  15.     // 此時userName的格式為:UserDomainName\LoginName  
  16.     // 我們只需要后面的LoginName就可以了。  
  17.  
  18.     string[] array = userName.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);  
  19.     if( array.Length == 2 )  
  20.         return array[1];  
  21.  
  22.     return null;  

在ASP.NET中使用Windows身份認(rèn)證時,IIS和WindowsAuthenticationModule已經(jīng)做了許多驗證用戶的相關(guān)工作,雖然我們可以使用前面的代碼獲取到用戶的登錄名,但用戶的其它信息即需要我們自己來獲取。在實際使用Windows身份認(rèn)證時,我們要做的事:基本上就是從Active Directory中根據(jù)用戶的登錄名獲取所需的各種信息。

比如:我的程序在運行時,還需要使用以下與用戶相關(guān)的信息:

  1. public sealed class UserInfo  
  2. {  
  3.     public string GivenName;  
  4.     public string FullName;  
  5.     public string Email;  

那么,我們可以使用這樣的代碼來獲取所需的用戶信息:

  1. public static class UserHelper  
  2. {  
  3.     /// <summary>  
  4.     /// 活動目錄中的搜索路徑,也可根據(jù)實際情況來修改這個值。  
  5.     /// </summary>  
  6.     public static string DirectoryPath = "LDAP://" + GetDomainName();  
  7.  
  8.  
  9.     /// <summary>  
  10.     /// 獲取與指定HttpContext相關(guān)的用戶信息  
  11.     /// </summary>  
  12.     /// <param name="context"></param>  
  13.     /// <returns></returns>  
  14.     public static UserInfo GetCurrentUserInfo(HttpContext context)  
  15.     {  
  16.         string loginName = GetUserLoginName(context);  
  17.         ifstring.IsNullOrEmpty(loginName) )  
  18.             return null;  
  19.  
  20.         return GetUserInfoByLoginName(loginName);  
  21.     }  
  22.  
  23.     /// <summary>  
  24.     /// 根據(jù)指定的HttpContext對象,獲取登錄名。  
  25.     /// </summary>  
  26.     /// <param name="context"></param>  
  27.     /// <returns></returns>  
  28.     public static string GetUserLoginName(HttpContext context)  
  29.     {  
  30.         if( context == null )  
  31.             return null;  
  32.  
  33.         if( context.Request.IsAuthenticated == false )  
  34.             return null;  
  35.  
  36.         string userName = context.User.Identity.Name;  
  37.         // 此時userName的格式為:UserDomainName\LoginName  
  38.         // 我們只需要后面的LoginName就可以了。  
  39.  
  40.         string[] array = userName.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);  
  41.         if( array.Length == 2 )  
  42.             return array[1];  
  43.  
  44.         return null;  
  45.     }  
  46.       
  47.  
  48.     /// <summary>  
  49.     /// 根據(jù)登錄名查詢活動目錄,獲取用戶信息。  
  50.     /// </summary>  
  51.     /// <param name="loginName"></param>  
  52.     /// <returns></returns>  
  53.     public static UserInfo GetUserInfoByLoginName(string loginName)  
  54.     {  
  55.         ifstring.IsNullOrEmpty(loginName) )  
  56.             return null;  
  57.  
  58.         // 下面的代碼將根據(jù)登錄名查詢用戶在AD中的信息。  
  59.         // 為了提高性能,可以在此處增加一個緩存容器(Dictionary or Hashtable)。  
  60.  
  61.         try {  
  62.             DirectoryEntry entry = new DirectoryEntry(DirectoryPath);  
  63.             DirectorySearcher search = new DirectorySearcher(entry);  
  64.             search.Filter = "(SAMAccountName=" + loginName + ")";  
  65.  
  66.             search.PropertiesToLoad.Add("givenName");  
  67.             search.PropertiesToLoad.Add("cn");  
  68.             search.PropertiesToLoad.Add("mail");  
  69.             // 如果還需要從AD中獲取其它的用戶信息,請參考ActiveDirectoryDEMO  
  70.  
  71.             SearchResult result = search.FindOne();  
  72.  
  73.             if( result != null ) {  
  74.                 UserInfo info = new UserInfo();  
  75.                 info.GivenName = result.Properties["givenName"][0].ToString();  
  76.                 info.FullName = result.Properties["cn"][0].ToString();  
  77.                 info.Email = result.Properties["mail"][0].ToString();  
  78.                 return info;  
  79.             }  
  80.         }  
  81.         catch {  
  82.             // 如果需要記錄異常,請在此處添加代碼。  
  83.         }  
  84.         return null;  
  85.     }  
  86.  
  87.  
  88.     private static string GetDomainName()  
  89.     {  
  90.         // 注意:這段代碼需要在Windows XP及較新版本的操作系統(tǒng)中才能正常運行。  
  91.         SelectQuery query = new SelectQuery("Win32_ComputerSystem");  
  92.         using( ManagementObjectSearcher searcher = new ManagementObjectSearcher(query) ) {  
  93.             foreach( ManagementObject mo in searcher.Get() ) {  
  94.                 if( (bool)mo["partofdomain"] )  
  95.                     return mo["domain"].ToString();  
  96.             }  
  97.         }  
  98.         return null;  
  99.     }  
  100.  

使用UserHelper的頁面代碼:

  1. <html xmlns="http://www.w3.org/1999/xhtml"> 
  2. <head> 
  3.     <title>WindowsAuthentication DEMO  - http://www.cnblogs.com/fish-li/</title> 
  4. </head> 
  5. <body> 
  6. <% if( Request.IsAuthenticated ) { %> 
  7.     當(dāng)前登錄全名:<%= Context.User.Identity.Name.HtmlEncode()%> <br /> 
  8.       
  9.     <% var user = UserHelper.GetCurrentUserInfo(Context); %> 
  10.     <% if( user != null ) { %> 
  11.         用戶短名:<%= user.GivenName.HtmlEncode()%> <br /> 
  12.         用戶全名:<%= user.FullName.HtmlEncode() %> <br /> 
  13.         郵箱地址:<%= user.Email.HtmlEncode() %> 
  14.     <% } %>      
  15. <% } else { %> 
  16.     當(dāng)前用戶還未登錄。  
  17. <% } %> 
  18. </body> 
  19. </html> 

程序運行的效果如下:

另外,還可以從Active Directory查詢一個叫做memberof的屬性(它與Windows用戶組無關(guān)),有時候可以用它區(qū)分用戶,設(shè)計與權(quán)限相關(guān)的操作。

在設(shè)計數(shù)據(jù)持久化的表結(jié)構(gòu)時,由于此時沒有“用戶表”,那么我們可以直接保存用戶的登錄名。剩下的開發(fā)工作就與Forms身份認(rèn)證沒有太多的差別了。

使用Active Directory驗證用戶身份

前面介紹了ASP.NET Windows身份認(rèn)證,在這種方式下,IIS和WindowsAuthenticationModule為我們實現(xiàn)了用戶身份認(rèn)證的過程。然而,有時可能由于各種原因,需要我們以編程的方式使用Active Directory驗證用戶身份,比如:在WinForm程序,或者其它的驗證邏輯。

我們不僅可以從Active Directory中查詢用戶信息,也可以用它來實現(xiàn)驗證用戶身份,這樣便可以實現(xiàn)自己的登錄驗證邏輯。

不管是如何使用Active Directory,我們都需要使用DirectoryEntry和DirectorySearcher這二個對象。 DirectoryEntry還提供一個構(gòu)造函數(shù)可讓我們輸入用戶名和密碼:

  1. // 摘要:  
  2. //     初始化 System.DirectoryServices.DirectoryEntry 類的新實例。  
  3. //  
  4. // 參數(shù):  
  5. //   Password:  
  6. //     在對客戶端進行身份驗證時使用的密碼。DirectoryEntry.Password 屬性初始化為該值。  
  7. //  
  8. //   username:  
  9. //     在對客戶端進行身份驗證時使用的用戶名。DirectoryEntry.Username 屬性初始化為該值。  
  10. //  
  11. //   Path:  
  12. //     此 DirectoryEntry 的路徑。DirectoryEntry.Path 屬性初始化為該值。  
  13. public DirectoryEntry(string path, string username, string password); 

要實現(xiàn)自己的登錄檢查,就需要使用這個構(gòu)造函數(shù)。以下是我寫用WinForm寫的一個登錄檢查的示例:

  1. private void btnLogin_Click(object sender, EventArgs e)  
  2. {  
  3.     if( txtUsername.Text.Length == 0 || txtPassword.Text.Length == 0 ) {  
  4.         MessageBox.Show("用戶名或者密碼不能為空。"this.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);  
  5.         return;  
  6.     }  
  7.  
  8.     string ldapPath = "LDAP://" + GetDomainName();  
  9.     string domainAndUsername = Environment.UserDomainName + "\\" + txtUsername.Text;  
  10.     DirectoryEntry entry = new DirectoryEntry(ldapPath, domainAndUsername, txtPassword.Text);  
  11.  
  12.     DirectorySearcher search = new DirectorySearcher(entry);  
  13.  
  14.     try {  
  15.         SearchResult result = search.FindOne();  
  16.  
  17.         MessageBox.Show("登錄成功。"this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);  
  18.     }  
  19.     catch( Exception ex ) {  
  20.         // 如果用戶名或者密碼不正確,也會拋出異常。  
  21.         MessageBox.Show(ex.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Stop);  
  22.     }  

程序運行的效果如下:

安全上下文與用戶模擬

在ASP.NET Windows身份認(rèn)證環(huán)境中,與用戶相關(guān)的安全上下文對象保存在HttpContext.User屬性中,是一個類型為WindowsPrincipal的對象,我們還可以訪問HttpContext.User.Identity來獲取經(jīng)過身份認(rèn)證的用戶標(biāo)識,它是一個WindowsIdentity類型的對象。

在.NET Framework中,我們可以通過WindowsIdentity.GetCurrent()獲取與當(dāng)前線程相關(guān)的WindowsIdentity對象,這種方法獲取的是當(dāng)前運行的Win32線程的安全上下文標(biāo)識。由于ASP.NET運行在IIS進程中,因此ASP.NET線程的安全標(biāo)識其實是從IIS的進程中繼承的,所以此時用二種方法得到的WindowsIdentity對象其實是不同的。

在Windows操作系統(tǒng)中,許多權(quán)限檢查都是基于Win32線程的安全上下文標(biāo)識,于是前面所說的二種WindowsIdentity對象會造成編程模型的不一致問題,為了解決這個問題,ASP.NET提供了“模擬”功能,允許線程以特定的Windows帳戶的安全上下文來訪問資源。

為了能更好的理解模擬的功能,我準(zhǔn)備了一個示例(ShowWindowsIdentity.ashx):

  1. public class ShowWindowsIdentity : IHttpHandler {  
  2.       
  3.     public void ProcessRequest (HttpContext context) {  
  4.         // 要觀察【模擬】的影響,  
  5.         // 可以啟用,禁止web.config中的設(shè)置:<identity impersonate="true"/>  
  6.           
  7.         context.Response.ContentType = "text/plain";  
  8.  
  9.         context.Response.Write(Environment.UserDomainName + "\\" + Environment.UserName + "\r\n");  
  10.           
  11.         WindowsPrincipal winPrincipal = (WindowsPrincipal)HttpContext.Current.User;  
  12.         context.Response.Write(string.Format("HttpContext.Current.User.Identity: {0}, {1}\r\n",   
  13.                 winPrincipal.Identity.AuthenticationType, winPrincipal.Identity.Name));  
  14.           
  15.         WindowsPrincipal winPrincipal2 = (WindowsPrincipal)Thread.CurrentPrincipal;  
  16.         context.Response.Write(string.Format("Thread.CurrentPrincipal.Identity: {0}, {1}\r\n",  
  17.                 winPrincipal2.Identity.AuthenticationType, winPrincipal2.Identity.Name));  
  18.  
  19.         WindowsIdentity winId = WindowsIdentity.GetCurrent();  
  20.         context.Response.Write(string.Format("WindowsIdentity.GetCurrent(): {0}, {1}",  
  21.                 winId.AuthenticationType, winId.Name));  
  22.     } 

首先,在web.config中設(shè)置:

  1. <authentication mode="Windows" /> 

注意:要把網(wǎng)站部署在IIS中,否則看不出效果。

此時,訪問ShowWindowsIdentity.ashx,將看到如下圖所示的結(jié)果:

現(xiàn)在修改一下web.config中設(shè)置:(注意:后面加了一句配置

  1. <authentication mode="Windows" /> 
  2. <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獲取當(dāng)前用戶標(biāo)識,那么就不存在問題(此時可以不需要模擬),例如FileAuthorizationModule就是這樣處理的。

2. 模擬只是在ASP.NET應(yīng)用程序訪問Windows系統(tǒng)資源時需要應(yīng)用Windows的安全檢查功能才會有用。

3. Forms身份認(rèn)證也能配置模擬功能,但只能模擬一個Windows帳戶。

4. 絕大多數(shù)情況下是不需要模擬的。

在IIS中配置Windows身份認(rèn)證

與使用Forms身份認(rèn)證的程序不同,使用Windows身份認(rèn)證的程序需要額外的配置步驟。這個小節(jié)將主要介紹在IIS中配置Windows身份認(rèn)證,我將常用的IIS6和IIS7.5為例分別介紹這些配置。

IIS6的配置 請參考下圖:

 

IIS7.5的配置 請參考下圖:

注意:Windows身份認(rèn)證是需要安裝的,方法請參考下圖:

關(guān)于瀏覽器的登錄對話框問題

當(dāng)我們用瀏覽器訪問一個使用Windows身份認(rèn)證的網(wǎng)站時,瀏覽器都會彈出一個對話框(左IE,右Safari):

此時,要求我們輸入Windows的登錄帳號,然后交給IIS驗證身份。

首次彈出這個對話框很正常:因為程序要驗證用戶的身份。

然而,每次關(guān)閉瀏覽器下次重新打開頁面時,又會出現(xiàn)此對話框,此時感覺就很不方便了。

雖然有些瀏覽器能記住用戶名和密碼,但我發(fā)現(xiàn)FireFox,Opera,Chrome仍然會彈出這個對話框,等待我們點擊確定,只有Safari才不會打擾用戶直接打開網(wǎng)頁。 IE的那個“記住我的密碼”復(fù)選框完全是個擺設(shè),它根本不會記住密碼!

因此,我所試過的所有瀏覽器中,只有Safari是最人性化的。

雖然在默認(rèn)情況下,雖然IE不會記住密碼,每次都需要再次輸入。

不過,IE卻可以支持不提示用戶輸入登錄帳號而直接打開網(wǎng)頁, 此時IE將使用用戶的當(dāng)前Windows登錄帳號傳遞給IIS驗證身份。

要讓IE打開一個Windows身份認(rèn)證的網(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頁中引用的所有對象的適當(dāng)?shù)奈募到y(tǒng)(NTFS)權(quán)限。

6. 用戶必須用域帳號登錄到Windows 。

在這幾個條件中,如果網(wǎng)站是在一個Windows域中運行,除了第3條可能不滿足外,其它條件應(yīng)該都容易滿足(第4條是默認(rèn)值)。因此,要讓IE不提示輸入登錄帳號,只要確保第3條滿足就可以了。下面的圖片演示了如何完成這個配置:(注意:配置方法也適合用域名訪問的情況)

 

另外,除了在IE中設(shè)置Intranet外,還可以在訪問網(wǎng)站時,用計算機名代替IP地址或者域名,那么IE始終認(rèn)為是在訪問Intranet內(nèi)的網(wǎng)站,此時也不會彈出登錄對話框。

在此,我想再啰嗦三句:

1. IE在集成Windows身份認(rèn)證時,雖然不提示登錄對話框,但是不表示不安全,它會自動傳遞登錄憑據(jù)。

2. 這種行為只有IE才能支持。(其它的瀏覽器只是會記住密碼,在實現(xiàn)上其實是不一樣的。)

3. 集成Windows身份認(rèn)證,也只適合在Intranet的環(huán)境中使用。

在客戶端代碼中訪問Windows身份認(rèn)證的頁面

在上篇博客中,我演示了如何用代碼訪問一個使用Forms身份認(rèn)證的網(wǎng)站中的受限頁面,方法是使用CookieContainer對象接收服務(wù)端生的登錄Cookie。然而,在Windows身份認(rèn)證的網(wǎng)站中,身份驗證的過程發(fā)生在IIS中,而且根本不使用Cookie保存登錄狀態(tài),而是需要在請求時發(fā)送必要的身份驗證信息。

在使用代碼做為客戶端訪問Web服務(wù)器時,我們?nèi)匀恍枰褂肏ttpWebRequest對象。為了能讓HttpWebRequest在訪問IIS時發(fā)送必要的身份驗證信息,HttpWebRequest提供二個屬性都可以完成這個功能:

  1. // 獲取或設(shè)置請求的身份驗證信息。  
  2. //  
  3. // 返回結(jié)果:  
  4. //     包含與該請求關(guān)聯(lián)的身份驗證憑據(jù)的 System.Net.ICredentials。默認(rèn)為 null。  
  5. public override ICredentials Credentials { getset; }  
  6.  
  7.  
  8. // 獲取或設(shè)置一個 System.Boolean 值,該值控制默認(rèn)憑據(jù)是否隨請求一起發(fā)送。  
  9. //  
  10. // 返回結(jié)果:  
  11. //     如果使用默認(rèn)憑據(jù),則為 true;否則為 false。默認(rèn)值為 false。  
  12. public override bool UseDefaultCredentials { getset; } 

下面是我準(zhǔn)備的完整的示例代碼(注意代碼中的注釋)

  1. static void Main(string[] args)  
  2. {  
  3.     try {  
  4.         // 請把WindowsAuthWebSite1這個網(wǎng)站部署在IIS中,  
  5.         // 開啟Windows認(rèn)證方式,并禁止匿名用戶訪問。  
  6.         // 然后修改下面的訪問地址。  
  7.         HttpWebRequest request =   
  8.             (HttpWebRequest)WebRequest.Create("http://localhost:33445/Default.aspx");  
  9.  
  10.         // 下面三行代碼,啟用任意一行都是可以的。  
  11.         request.UseDefaultCredentials = true;  
  12.         //request.Credentials = CredentialCache.DefaultCredentials;  
  13.         //request.Credentials = CredentialCache.DefaultNetworkCredentials;  
  14.         // 如果上面的三行代碼全被注釋了,那么將會看到401的異常信息。  
  15.  
  16.         using( HttpWebResponse response = (HttpWebResponse)request.GetResponse() ) {  
  17.             using( StreamReader sr = new StreamReader(response.GetResponseStream()) ) {  
  18.                 Console.WriteLine(sr.ReadToEnd());  
  19.             }  
  20.         }  
  21.     }  
  22.     catch( WebException wex ) {  
  23.         Console.WriteLine("=====================================");  
  24.         Console.WriteLine("異常發(fā)生了。");  
  25.         Console.WriteLine("=====================================");  
  26.         Console.WriteLine(wex.Message);  
  27.     }  

其實關(guān)鍵部分還是設(shè)置UseDefaultCredentials或者Credentials,代碼中的三種方法是有效的。

這三種方法的差別:
1. Credentials = CredentialCache.DefaultCredentials; 表示在發(fā)送請求會帶上當(dāng)前用戶的身份驗證憑據(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。

在結(jié)束這篇博客之前,我想我應(yīng)該感謝新蛋。

在新蛋的網(wǎng)絡(luò)環(huán)境中,讓我學(xué)會了使用Windows身份認(rèn)證。

除了感謝之外,我現(xiàn)在還特別懷念 fl45 這個登錄名......

點擊此處下載示例代碼

原文鏈接:http://www.cnblogs.com/fish-li/archive/2012/05/07/2486840.html

 

責(zé)任編輯:彭凡 來源: 博客園
相關(guān)推薦

2012-04-16 09:54:26

2009-12-10 17:47:01

ASP.NET 2.0

2009-07-29 12:55:44

ASP.NET身份驗證

2011-05-23 10:37:03

2009-08-03 14:22:33

什么是ASP.NET

2009-07-28 17:17:19

ASP.NET概述

2009-07-22 17:45:35

ASP.NET教程

2009-07-23 16:59:31

ASP.NET認(rèn)證Form表單

2009-07-29 15:51:29

ASP.NET中執(zhí)行w

2021-02-17 08:51:55

cookie身份驗證

2009-07-27 12:22:03

ASP.NET和ASPASP.NET入門教程

2009-07-28 16:31:03

Windows 200

2009-07-28 12:42:17

.NET關(guān)機代碼

2009-07-29 17:11:25

ASP.NET ISA

2009-08-10 13:32:15

ASP.NET TimASP.NET組件設(shè)計

2009-07-29 16:08:07

ASP和ASP.NET

2024-05-06 00:00:00

ASP.NET授權(quán)機制

2012-06-04 09:36:50

2009-07-29 16:47:40

ASP.NET表單身份

2009-07-28 09:02:32

asp.net aja
點贊
收藏

51CTO技術(shù)棧公眾號

少妇伦子伦精品无吗| 91久久久一线二线三线品牌| 亚洲精品午夜视频| 巨胸喷奶水www久久久| 亚洲欧洲av在线| 国产伦精品一区二区三区照片91 | 91手机视频在线观看| 久久亚洲成人av| 精品国产一级毛片| 精品少妇一区二区三区在线播放| 黄色a级片免费| 伊人手机在线| 国产精品系列在线| 国产精品v欧美精品∨日韩| 黄色av一区二区| 影音先锋亚洲电影| av成人资源网| 午夜精品福利一区二区三区av | 亚洲国产精品自拍| 亚洲二区三区四区| 天天舔天天干天天操| 极品少妇一区二区三区精品视频 | 久久久久久日产精品| 91亚洲一区精品| 最近中文字幕免费观看| 国产一区二区你懂的| 欧美日本国产在线| frxxee中国xxx麻豆hd| 国产亚洲一区| 日韩电影中文字幕在线| 在线观看亚洲免费视频| 老司机亚洲精品一区二区| 在线中文字幕一区二区| 春日野结衣av| 高清视频在线观看三级| 夜色激情一区二区| 天天成人综合网| 无遮挡动作视频在线观看免费入口| 91影院在线观看| 国产在线一区二区三区四区| 亚洲国产精品一| 国产精品中文字幕日韩精品| 成人国产在线激情| 亚洲av无码乱码国产精品fc2| 亚洲久色影视| 97在线视频免费看| 动漫精品一区一码二码三码四码| 欧美有码视频| 欧美精品情趣视频| 欧美激情国产精品免费| 亚洲自拍偷拍网| 久久艹在线视频| 视频这里只有精品| 自拍偷拍欧美| 欧美大片免费观看| 欧美精品乱码视频一二专区| 中文字幕码精品视频网站| 欧美jizz19性欧美| 日韩hd视频在线观看| 中文字幕 日本| 日韩最新在线| 亚洲情综合五月天| 我不卡一区二区| 日韩欧美电影| 麻豆国产精品va在线观看不卡| 亚洲怡红院在线观看| 一区二区蜜桃| 国a精品视频大全| 日本一区二区不卡在线| 9色国产精品| 欧美主播福利视频| 中文字幕+乱码+中文| 国产在线国偷精品产拍免费yy| 92福利视频午夜1000合集在线观看| 精品人妻少妇AV无码专区| 国产.精品.日韩.另类.中文.在线.播放| 国产精品国产三级国产专区53 | 九七电影院97理论片久久tvb| 欧美日韩一级二级三级| 中文字幕一区二区三区四| 亚洲啊v在线免费视频| 日韩电影免费在线观看中文字幕| caopeng视频| 日韩av二区| 欧美成人午夜影院| 偷偷操不一样的久久| 日韩有码一区二区三区| 69174成人网| 日韩精品系列| 国产精品久久久久影院| 国产一区二区四区| 亚洲第一影院| 日韩欧美另类在线| 丰腴饱满的极品熟妇| 国产精品福利在线观看播放| 欧美激情手机在线视频| 国产精品久久久久久久久久久久久久久久久 | 日本丰满少妇做爰爽爽| 国产精品一区二区果冻传媒| 爽好多水快深点欧美视频| 久久精品99久久香蕉国产色戒| 精品深夜av无码一区二区老年| 久久精品电影| 99www免费人成精品| 九九在线视频| 亚洲午夜精品网| 中文字幕天天干| 岛国精品一区| www.久久久久久.com| 日韩三级视频在线播放| 麻豆91精品91久久久的内涵| 精品日韩电影| 大片免费在线看视频| 一本久道久久综合中文字幕| 91大神免费观看| 国产探花在线精品| 国产69精品99久久久久久宅男| 在线视频1卡二卡三卡| 99re亚洲国产精品| bt天堂新版中文在线地址| yw.尤物在线精品视频| 亚洲精品97久久| 精品99在线观看| 蜜桃视频一区二区三区| 欧美午夜精品久久久久免费视| 欧美日韩色网| 制服丝袜亚洲精品中文字幕| 国产精品无码久久久久一区二区| 欧美日韩影院| 国产欧美日韩中文字幕在线| 日韩有码电影| 精品久久久在线观看| 性xxxxxxxxx| 欧美va亚洲va日韩∨a综合色| 国产日韩换脸av一区在线观看| 黄色片在线看| 一本久道久久综合中文字幕 | 中文字幕在线观看免费| 91老司机福利 在线| www.av片| 麻豆一区二区| 91精品国产91久久| 午夜视频福利在线| 高潮白浆女日韩av免费看| 亚洲成av人片在线观看无| 欧美视频一区| 日韩欧美亚洲范冰冰与中字| 国产精品99一区| 欧日韩在线视频| 一区二区视频在线看| 在线观看网站黄| 国产精品毛片久久| 成人看片人aa| 成人在线免费看片| 日韩欧美在线观看一区二区三区| 欧美做爰爽爽爽爽爽爽| 国产精品一级黄| 国产在线观看欧美| 亚洲综合网站| 久久久久久国产精品美女| 亚洲成人精品女人久久久| 一区二区三区中文字幕精品精品| 欧美日韩一区二区区| 欧美激情综合| 成人免费看片网站| av剧情在线观看| 国产视频欧美视频| 国产精品无码一区| 亚洲欧美偷拍卡通变态| 性活交片大全免费看| 伊人久久大香线蕉av超碰演员| 狠狠爱一区二区三区| 日韩影片中文字幕| 主播福利视频一区| 精品国产亚洲AV| 五月开心婷婷久久| 国产肥白大熟妇bbbb视频| 免费精品视频在线| 菠萝蜜视频在线观看入口| 全球av集中精品导航福利| 国产z一区二区三区| 国产盗摄在线观看| 亚洲精品第一国产综合精品| 国产成人无码专区| 亚洲精品视频自拍| 草草影院第一页| 激情欧美日韩一区二区| 99久久久精品视频| 经典一区二区| 91九色在线观看| 成人开心激情| 久热爱精品视频线路一| 青青草视频在线免费观看| 在线成人小视频| 毛片在线免费视频| 亚洲日本乱码在线观看| 粉嫩av懂色av蜜臀av分享| 美女视频免费一区| 免费看欧美黑人毛片| 国产a级免费视频| 影音先锋在线一区| 蜜桃视频在线观看91| 国产一区一区| 欧美最猛性xxxx| 色www永久免费视频首页在线| 亚洲欧美中文日韩在线v日本| 国产女人18毛片18精品| 欧美日韩亚洲视频| 唐朝av高清盛宴| 欧美国产视频在线| a天堂视频在线观看| 精品一区二区三区免费播放 | 丝袜综合欧美| 色先锋资源久久综合5566| 日本激情视频网站| 91精品国产91久久久久久最新毛片 | 免费在线国产| 精品99999| 国产成人av免费看| 欧美另类变人与禽xxxxx| 国产综合精品视频| 亚洲一区电影777| 国产精品久久久久久久精| 国产精品麻豆久久久| 亚洲永久精品ww.7491进入| 成人高清在线视频| 337p日本欧洲亚洲大胆张筱雨 | 国产精品一级黄片| 国产一区不卡在线| 国产一伦一伦一伦| 日韩高清在线一区| av动漫在线观看| 国产一区二区三区四区老人| 看一级黄色录像| 日韩免费一区| 亚洲精品日韩精品| 欧美日韩一区二区综合| 欧美三级华人主播| 宅男在线一区| 日本精品一区| 国产精品免费不| 欧美日韩在线高清| 久久成人高清| 欧美日韩成人一区二区三区| 亚洲人成精品久久久| 老牛影视免费一区二区| 欧美久久精品| 免费久久久一本精品久久区| 亚洲精品无吗| 免费国产一区| 欧美日韩国产免费观看视频| 午夜久久资源| 亚洲精品国产偷自在线观看| 亚洲香蕉伊综合在人在线视看| 色www免费视频| 日日摸夜夜添夜夜添精品视频| 热久久精品免费视频| 日日摸夜夜添夜夜添国产精品| 精品久久久久久中文字幕2017| 免费在线观看视频一区| 国产色视频在线播放| 国产一区在线视频| 污污免费在线观看| 91丨porny丨在线| 六月婷婷七月丁香| 欧美激情一区二区三区四区| 91久久久久久久久久久久久久| 亚洲欧洲精品天堂一级| 国产这里有精品| 天天综合日日夜夜精品| 欧美日韩综合一区二区三区| 欧美三级韩国三级日本三斤| 91精品国产色综合久久不8| 欧美一区二区三区免费观看视频 | 亚洲欧美日韩视频一区| 成人精品一区| 久久伊人精品一区二区三区| 丰满大乳少妇在线观看网站| 欧洲永久精品大片ww免费漫画| 国产69精品久久久久按摩| 444亚洲人体| 最新国产一区| 99re6这里有精品热视频| av成人毛片| www.久久av.com| proumb性欧美在线观看| 老司机福利在线观看| 尤物在线观看一区| 亚洲成熟少妇视频在线观看| 91精品国产综合久久婷婷香蕉 | 中文字幕在线观看高清| 日韩欧美一级特黄在线播放| 色视频精品视频在线观看| 社区色欧美激情 | xxxx在线视频| 成人精品久久久| 九九久久精品| 国产成人永久免费视频| 日韩精品乱码av一区二区| 第一页在线视频| 日本一区二区免费在线观看视频 | 欧美天堂在线观看| 国产手机av在线| 国产午夜精品全部视频播放| 牛牛电影国产一区二区| 国产精品久久中文| 奇米影视777在线欧美电影观看| 黄色a级在线观看| 久久裸体视频| av av在线| 亚洲人精品午夜| 国产日韩欧美在线| 国产在视频一区二区三区吞精| 国产另类自拍| 欧美va天堂| 污污网站免费观看| 久久久久久一级片| 国产做受高潮漫动| 日韩小视频在线观看专区| 国产精品久久一区二区三区不卡| 午夜精品福利视频| 亚洲三区欧美一区国产二区| 一区二区免费在线视频| 久久亚洲国产精品一区二区| 中文字幕在线视频播放| 亚洲激情校园春色| 国产欧美日韩综合精品一区二区三区| 国产午夜精品全部视频播放| videos性欧美另类高清| 狠狠色伊人亚洲综合网站色| 国产精品va| www.美色吧.com| 樱桃视频在线观看一区| 国产黄频在线观看| 欧美人与物videos| 人人爱人人干婷婷丁香亚洲| 一道本在线观看视频| 久久国产综合精品| 2017亚洲天堂| 欧美日韩1区2区| 美女免费久久| 亚洲a级在线播放观看| 香蕉国产精品| 精品综合久久久久| 中文字幕色av一区二区三区| 91免费视频播放| 久久精品国产2020观看福利| 欧美风情在线视频| 亚洲第一页在线视频| 国产一区二区剧情av在线| 国产一区二区三区视频播放| 欧美色网一区二区| 色三级在线观看| 亚洲一区二区久久久久久久| 亚洲综合婷婷| 久久精品aⅴ无码中文字字幕重口| 亚洲综合色成人| 天堂在线中文| 国产精品久久久久久久久久免费| 清纯唯美日韩| 国产成人强伦免费视频网站| 亚洲国产一区在线观看| 亚洲AV第二区国产精品| 国产成人精品最新| 久久美女视频| 三大队在线观看| 欧美日韩亚洲精品一区二区三区| 国产在线资源| 成人a在线视频| 雨宫琴音一区二区在线| 免费在线观看成年人视频| 欧洲精品在线观看| 黄网页在线观看| 国产一区在线观| 美日韩一级片在线观看| 久久免费少妇高潮99精品| 精品亚洲国产成av人片传媒| 91亚洲精品| 真人抽搐一进一出视频| 久久麻豆一区二区| 国产按摩一区二区三区| 国产91成人video| 日韩电影免费在线观看| 国产精九九网站漫画| 色综合中文字幕| 99福利在线| 欧美一区二区综合| 国产精品一二三在| 黄色av一区二区| 久久久久久久一区二区三区| 国产影视一区| 岛国精品一区二区三区| 91官网在线免费观看| 免费污视频在线观看| 日韩欧美在线观看强乱免费| 福利一区福利二区| 在线观看一二三区| 国产91精品黑色丝袜高跟鞋| 91精品国偷自产在线电影 | 日本一区二区成人在线|