细说ASP.NET Windows身份认证

阅读目录

  • 开始
  • 认识ASP.NET Windows身份认证
  • 访问 Active Directory
  • 在ASP.NET中访问Active Directory
  • 使用Active Directory验证用户身份
  • 安全上下文与用户模拟
  • 在IIS中配置Windows身份认证
  • 关于浏览器的登录对话框问题
  • 在客户端代码中访问Windows身份认证的页面

上篇博客我谈到了一些关于ASP.NET Forms身份认证方面的话题,这次的博客将主要介绍ASP.NET Windows身份认证。

Forms身份认证虽然使用广泛,不过,如果是在 Windows Active Directory 的环境中使用ASP.NET, 那么使用Windows身份认证也会比较方便。 方便性表现为:我们不用再设计登录页面,不用编写登录验证逻辑。而且使用Windows身份认证会有更好的安全保障。

回到顶部

认识ASP.NET Windows身份认证

要使用Windows身份认证模式,需要在web.config设置:

<authentication mode="Windows" />

Windows身份认证做为ASP.NET的默认认证方式,与Forms身份认证在许多基础方面是一样的。上篇博客我说过:我认为ASP.NET的身份认证的最核心部分其实就是HttpContext.User这个属性所指向的对象。在接下来的部分,我将着重分析这个对象在二种身份认证中有什么差别。

在ASP.NET身份认证过程中,IPrincipal和IIdentity这二个接口有着非常重要的作用。 前者定义用户对象的基本功能,后者定义标识对象的基本功能, 不同的身份认证方式得到的这二个接口的实例也是不同的。

ASP.NET Windows身份认证是由WindowsAuthenticationModule实现的。WindowsAuthenticationModule在ASP.NET管线的AuthenticateRequest事件中, 使用从IIS传递到ASP.NET的Windows访问令牌(Token)创建一个WindowsIdentity对象,Token通过调用context.WorkerRequest.GetUserToken()获得, 然后再根据WindowsIdentity 对象创建WindowsPrincipal对象, 然后把它赋值给HttpContext.User。

在Forms身份认证中,我们需要创建登录页面,让用户提交用户名和密码,然后检查用户名和密码的正确性, 接下来创建一个包含FormsAuthenticationTicket对象的登录Cookie供后续请求使用。FormsAuthenticationModule在ASP.NET管线的AuthenticateRequest事件中, 解析登录Cookie并创建一个包含FormsIdentity的GenericPrincipal对象, 然后把它赋值给HttpContext.User。

上面二段话简单了概括了二种身份认证方式的工作方式。 我们可以发现它们存在以下差别: 1. Forms身份认证需要Cookie表示登录状态,Windows身份认证则依赖于IIS 2. Windows身份认证不需要我们设计登录页面,不用编写登录验证逻辑,因此更容易使用。

在授权阶段,UrlAuthorizationModule仍然会根据当前用户检查将要访问的资源是否得到许可。 接下来,FileAuthorizationModule检查 HttpContext.User.Identity 属性中的 IIdentity 对象是否是 WindowsIdentity 类的一个实例。 如果 IIdentity 对象不是 WindowsIdentity 类的一个实例,则 FileAuthorizationModule 类停止处理。 如果存在 WindowsIdentity 类的一个实例,则 FileAuthorizationModule 类调用 AccessCheck Win32 函数(通过 P/Invoke) 来确定是否授权经过身份验证的客户端访问请求的文件。 如果该文件的安全描述符的随机访问控制列表 (DACL) 中至少包含一个 Read 访问控制项 (ACE),则允许该请求继续。 否则,FileAuthorizationModule 类调用 HttpApplication.CompleteRequest 方法并将状态码 401 返回到客户端。

在Windows身份认证中,验证工作主要是由IIS实现的,WindowsAuthenticationModule其实只是负责创建WindowsPrincipal和WindowsIdentity而已。 顺便介绍一下:Windows 身份验证又分为“NTLM 身份验证”和“Kerberos v5 身份验证”二种, 关于这二种Windows身份认证的更多说明可查看MSDN技术文章:解释:ASP.NET 2.0 中的 Windows 身份验证。 在我看来,IIS最终使用哪种Windows身份认证方式并不影响我们的开发过程,因此本文不会讨论这个话题。

根据我的实际经验来看,使用Windows身份认证时,主要的开发工作将是根据登录名从Active Directory获取用户信息。 因为,此时不需要我们再设计登录过程,IIS与ASP.NET已经为我们准备好了WindowsPrincipal和WindowsIdentity这二个与用户身份相关的对象。

回到顶部

访问 Active Directory

我们通常使用LDAP协议来访问Active Directory, 在.net framework中提供了DirectoryEntry和DirectorySearcher这二个类型让我们可以方便地从托管代码中访问 Active Directory 域服务。

如果我们要在"test.corp”这个域中搜索某个用户信息,我们可以使用下面的语句构造一个DirectoryEntry对象:

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

在这段代码中,我采用硬编码的方式把域名写进了代码。 我们如何知道当前电脑所使用的是哪个域名呢? 答案是:查看“我的电脑”的属性对话框:

注意:这个域名不一定与System.Environment.UserDomainName相同。

除了可以查看“我的电脑”的属性对话框外,我们还可以使用代码的方式获取当前电脑所使用的域名:

private static string GetDomainName()
{// 注意:这段代码需要在Windows XP及较新版本的操作系统中才能正常运行。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;
}

当构造了DirectorySearcher对象后,我们便可以使用DirectorySearcher来执行对Active Directory的搜索。 我们可以使用下面的步骤来执行搜索: 1. 设置 DirectorySearcher.Filter 指示LDAP格式筛选器,这是一个字符串。 2. 多次调用PropertiesToLoad.Add() 设置搜索过程中要检索的属性列表。 3. 调用FindOne() 方法获取搜索结果。

下面的代码演示了如何从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());}
}

结果如下:

在前面的代码,我在搜索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获取线程相关的用户名,但ASP.NET运行在IIS中,线程相关的用户名就不一定是客户端的用户名了。 不过,ASP.NET可以模拟用户方式运行,通过这种方式才可以得到正确的结果。关于“模拟”的话题在本文的后面部分有说明。

在ASP.NET中,为了能可靠的获取登录用户的登录名,我们可以使用下面的代码:

/// <summary>
/// 根据指定的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已经做了许多验证用户的相关工作, 虽然我们可以使用前面的代码获取到用户的登录名,但用户的其它信息即需要我们自己来获取。 在实际使用Windows身份认证时,我们要做的事:基本上就是从Active Directory中根据用户的登录名获取所需的各种信息。

比如:我的程序在运行时,还需要使用以下与用户相关的信息:

public sealed class UserInfo
{public string GivenName;public string FullName;public string Email;
}

那么,我们可以使用这样的代码来获取所需的用户信息:

public static class UserHelper
{/// <summary>/// 活动目录中的搜索路径,也可根据实际情况来修改这个值。/// </summary>public static string DirectoryPath = "LDAP://" + GetDomainName();/// <summary>/// 获取与指定HttpContext相关的用户信息/// </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>/// 根据指定的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>/// 根据登录名查询活动目录,获取用户信息。/// </summary>/// <param name="loginName"></param>/// <returns></returns>public static UserInfo GetUserInfoByLoginName(string loginName){if( string.IsNullOrEmpty(loginName) )return null;// 下面的代码将根据登录名查询用户在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中获取其它的用户信息,请参考ActiveDirectoryDEMOSearchResult 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及较新版本的操作系统中才能正常运行。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用户组无关),有时候可以用它区分用户,设计与权限相关的操作。

在设计数据持久化的表结构时,由于此时没有“用户表”,那么我们可以直接保存用户的登录名。 剩下的开发工作就与Forms身份认证没有太多的差别了。

回到顶部

使用Active Directory验证用户身份

前面介绍了ASP.NET Windows身份认证,在这种方式下,IIS和WindowsAuthenticationModule为我们实现了用户身份认证的过程。 然而,有时可能由于各种原因,需要我们以编程的方式使用Active Directory验证用户身份,比如:在WinForm程序,或者其它的验证逻辑。

我们不仅可以从Active Directory中查询用户信息,也可以用它来实现验证用户身份,这样便可以实现自己的登录验证逻辑。

不管是如何使用Active Directory,我们都需要使用DirectoryEntry和DirectorySearcher这二个对象。DirectoryEntry还提供一个构造函数可让我们输入用户名和密码:

// 摘要:
//     初始化 System.DirectoryServices.DirectoryEntry 类的新实例。
//
// 参数:
//   Password:
//     在对客户端进行身份验证时使用的密码。DirectoryEntry.Password 属性初始化为该值。
//
//   username:
//     在对客户端进行身份验证时使用的用户名。DirectoryEntry.Username 属性初始化为该值。
//
//   Path:
//     此 DirectoryEntry 的路径。DirectoryEntry.Path 属性初始化为该值。
public DirectoryEntry(string path, string username, string password);

要实现自己的登录检查,就需要使用这个构造函数。 以下是我写用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身份认证环境中,与用户相关的安全上下文对象保存在HttpContext.User属性中,是一个类型为WindowsPrincipal的对象, 我们还可以访问HttpContext.User.Identity来获取经过身份认证的用户标识,它是一个WindowsIdentity类型的对象。

在.NET Framework中,我们可以通过WindowsIdentity.GetCurrent()获取与当前线程相关的WindowsIdentity对象, 这种方法获取的是当前运行的Win32线程的安全上下文标识。 由于ASP.NET运行在IIS进程中,因此ASP.NET线程的安全标识其实是从IIS的进程中继承的, 所以此时用二种方法得到的WindowsIdentity对象其实是不同的。

在Windows操作系统中,许多权限检查都是基于Win32线程的安全上下文标识, 于是前面所说的二种WindowsIdentity对象会造成编程模型的不一致问题, 为了解决这个问题,ASP.NET提供了“模拟”功能,允许线程以特定的Windows帐户的安全上下文来访问资源。

为了能更好的理解模拟的功能,我准备了一个示例(ShowWindowsIdentity.ashx):

public class ShowWindowsIdentity : IHttpHandler {public void ProcessRequest (HttpContext context) {// 要观察【模拟】的影响,// 可以启用,禁止web.config中的设置:<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中设置:

<authentication mode="Windows" />

注意:要把网站部署在IIS中,否则看不出效果。

此时,访问ShowWindowsIdentity.ashx,将看到如下图所示的结果:

现在修改一下web.config中设置:(注意:后面加了一句配置

<authentication mode="Windows" />
<identity impersonate="true"/>

此时,访问ShowWindowsIdentity.ashx,将看到如下图所示的结果:

说明: 1. FISH-SRV2003是我的计算机名。它在一个没有域的环境中。 2. fish-li是我的一个Windows帐号的登录名。 3. 网站部署在IIS6中,进程以NETWORK SERVICE帐号运行。 4. 打开网页时,我输入的用户名是fish-li

前面二张图片的差异之处其实也就是ASP.NET的“模拟”所发挥的功能。

关于模拟,我想说四点: 1. 在ASP.NET中,我们应该访问HttpContext.User.Identity获取当前用户标识,那么就不存在问题(此时可以不需要模拟),例如FileAuthorizationModule就是这样处理的。 2. 模拟只是在ASP.NET应用程序访问Windows系统资源时需要应用Windows的安全检查功能才会有用。 3. Forms身份认证也能配置模拟功能,但只能模拟一个Windows帐户。 4. 绝大多数情况下是不需要模拟的。

回到顶部

在IIS中配置Windows身份认证

与使用Forms身份认证的程序不同,使用Windows身份认证的程序需要额外的配置步骤。 这个小节将主要介绍在IIS中配置Windows身份认证,我将常用的IIS6和IIS7.5为例分别介绍这些配置。

IIS6的配置 请参考下图:

IIS7.5的配置 请参考下图:

注意:Windows身份认证是需要安装的,方法请参考下图:

回到顶部

关于浏览器的登录对话框问题

当我们用浏览器访问一个使用Windows身份认证的网站时,浏览器都会弹出一个对话框(左IE,右Safari):

此时,要求我们输入Windows的登录帐号,然后交给IIS验证身份。

首次弹出这个对话框很正常:因为程序要验证用户的身份。 然而,每次关闭浏览器下次重新打开页面时,又会出现此对话框,此时感觉就很不方便了。 虽然有些浏览器能记住用户名和密码,但我发现FireFox,Opera,Chrome仍然会弹出这个对话框,等待我们点击确定, 只有Safari才不会打扰用户直接打开网页。IE的那个“记住我的密码”复选框完全是个摆设,它根本不会记住密码!

因此,我所试过的所有浏览器中,只有Safari是最人性化的。 虽然在默认情况下,虽然IE不会记住密码,每次都需要再次输入。 不过,IE却可以支持不提示用户输入登录帐号而直接打开网页,此时IE将使用用户的当前Windows登录帐号传递给IIS验证身份。

要让IE打开一个Windows身份认证的网站不提示登录对话框,必须满足以下条件: 1. 必须在 IIS 的 Web 站点属性中启用 Windows 集成身份验证。 2. 客户端和Web服务器都必须在基于Microsoft Windows的同一个域内。 3. Internet Explorer 必须把所请求的 URL 视为 Intranet(本地)。 4. Internet Explorer 的 Intranet 区域的安全性设置必须设为“只在 Intranet 区域自动登录”。 5. 请求Web页的用户必须具有访问该Web页以及该Web页中引用的所有对象的适当的文件系统(NTFS)权限。 6. 用户必须用域帐号登录到Windows 。

在这几个条件中,如果网站是在一个Windows域中运行,除了第3条可能不满足外,其它条件应该都容易满足(第4条是默认值)。 因此,要让IE不提示输入登录帐号,只要确保第3条满足就可以了。 下面的图片演示了如何完成这个配置:(注意:配置方法也适合用域名访问的情况)

另外,除了在IE中设置Intranet外,还可以在访问网站时,用计算机名代替IP地址或者域名, 那么IE始终认为是在访问Intranet内的网站,此时也不会弹出登录对话框。

在此,我想再啰嗦三句: 1. IE在集成Windows身份认证时,虽然不提示登录对话框,但是不表示不安全,它会自动传递登录凭据。 2. 这种行为只有IE才能支持。(其它的浏览器只是会记住密码,在实现上其实是不一样的。) 3. 集成Windows身份认证,也只适合在Intranet的环境中使用。

回到顶部

在客户端代码中访问Windows身份认证的页面

在上篇博客中,我演示了如何用代码访问一个使用Forms身份认证的网站中的受限页面,方法是使用CookieContainer对象接收服务端生的登录Cookie。 然而,在Windows身份认证的网站中,身份验证的过程发生在IIS中,而且根本不使用Cookie保存登录状态,而是需要在请求时发送必要的身份验证信息。

在使用代码做为客户端访问Web服务器时,我们仍然需要使用HttpWebRequest对象。 为了能让HttpWebRequest在访问IIS时发送必要的身份验证信息,HttpWebRequest提供二个属性都可以完成这个功能:

// 获取或设置请求的身份验证信息。
//
// 返回结果:
//     包含与该请求关联的身份验证凭据的 System.Net.ICredentials。默认为 null。
public override ICredentials Credentials { get; set; }// 获取或设置一个 System.Boolean 值,该值控制默认凭据是否随请求一起发送。
//
// 返回结果:
//     如果使用默认凭据,则为 true;否则为 false。默认值为 false。
public override bool UseDefaultCredentials { get; set; }

下面是我准备的完整的示例代码(注意代码中的注释)

static void Main(string[] args)
{try {// 请把WindowsAuthWebSite1这个网站部署在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("异常发生了。");Console.WriteLine("=====================================");Console.WriteLine(wex.Message);}
}

其实关键部分还是设置UseDefaultCredentials或者Credentials,代码中的三种方法是有效的。 这三种方法的差别: 1. Credentials = CredentialCache.DefaultCredentials; 表示在发送请求会带上当前用户的身份验证凭据。 2. UseDefaultCredentials = true; 此方法在内部会调用前面的方法,因此与前面的方法是一样的。 3. Credentials = CredentialCache.DefaultNetworkCredentials; 是在.NET 2.0中引用的新方法。

关于DefaultCredentials和DefaultNetworkCredentials的更多差别,请看我整理的表格:

Credentials属性 申明类型 实例类型 .NET支持版本
DefaultCredentials ICredentials SystemNetworkCredential 从1.0开始
DefaultNetworkCredentials NetworkCredential SystemNetworkCredential 从2.0开始

三个类型的继承关系: 1. NetworkCredential实现了ICredentials接口, 2. SystemNetworkCredential继承自NetworkCredential。

在结束这篇博客之前,我想我应该感谢新蛋。 在新蛋的网络环境中,让我学会了使用Windows身份认证。 除了感谢之外,我现在还特别怀念 fl45 这个登录名......

转载于:https://www.cnblogs.com/Griffin/archive/2012/06/16/2551873.html

[转载]细说ASP.NET Windows身份认证相关推荐

  1. 细说ASP.NET Forms身份认证

    细说ASP.NET Forms身份认证 阅读目录 开始 ASP.NET身份认证基础 ASP.NET身份认证过程 如何实现登录与注销 保护受限制的页面 登录页不能正常显示的问题 认识Forms身份认证 ...

  2. ASP.NET身份验证——Windows身份认证

    细说ASP.NET Windows身份认证 上篇博客我谈到了一些关于ASP.NET Forms身份认证方面的话题,这次的博客将主要介绍ASP.NET Windows身份认证. Forms身份认证虽然使 ...

  3. 实战解读ASP.NET Core身份认证

    长话短说:上文我们聊了 ASP.NET Core 基于声明的访问控制到底是什么鬼? 今天我们乘胜追击:聊一聊ASP.NET Core 中的身份验证. 身份验证是确定用户身份的过程.授权是确定用户是否有 ...

  4. asp.net form身份认证不定时认证失败的问题 排查

    1.网站出现form认证不定时认证失败.登陆过后 每隔一会儿就需要重新登陆.首先检查的是form身份认证票据设置的时间(正常) 然后检查加密后的身份认证信息写入的cookie的失效时间(正常) 2.这 ...

  5. ASP.NET MVC身份认证与授权

    文章目录 一.引言 1.身份认证的含义 2.身份认证与Session 基于Session保存用户状态 不足之处 二.ASP.NET身份验证 Forms验证 FormsAuthentication类 验 ...

  6. ASP.NET MVC --- 身份认证与授权

    身份认证的含义:例如在现在浏览的某宝电商网站中会经常遇到的情况,想要将某件商品加入到购物车,点击"加入购物车"之后弹出的却是登录界面.这个就是所谓的请求的身份认证 身份认证与Ses ...

  7. Asp.net core 身份认证框架 Microsoft Identity的使用以及如何使用Idengtity创建自带的用户模型SignInManager和UserManager的使用等等

    要启动身份认证组件,首先要更改数据库上下文中继承的关系,原本我们是继承于 Dbcontext这个类,现在我们需要继承IdentityDbContext 继承这个类,我们需要安装对应的框架, 如图: 这 ...

  8. C# ASP.NET Forms身份认证

    原文:https://www.cnblogs.com/kyo-lynn/p/3418577.html 原文:https://www.cnblogs.com/fish-li/archive/2012/0 ...

  9. IIS6文件权限不对触发了Windows身份认证问题解决方法

    今天在iis上调试程序的时候突然发现需要登录: 通过csdn提问得知可能是权限设置有问题于是设置了下internet来宾用户: 结果问题没有解决.后来想想应该不是问题,因为我在自己机器上调试用的是Ev ...

最新文章

  1. 左手程序员,右手作家:你必须会的Jupyter Notebook
  2. python 模拟用户点击浏览器_Python-模拟浏览器-下载文献
  3. MySQL的binlog日志
  4. 微信小程序之页面打开数量限制
  5. 【模型解读】从2D卷积到3D卷积,都有什么不一样
  6. k8s 手动恢复redis 集群_二进制手动部署k8s-1.14高可用集群(二、集群部署)
  7. 安装iproute2
  8. 【SSM面向CRUD编程专栏 7】springAop 事务控制
  9. nagios安装配置pnp4nagios-0.6.6
  10. python学习课后练习题_python初步学习-练习题
  11. PhoneGap在Android上的插件开发方法介绍
  12. java bufferedinputstream关闭_Java BufferedInputStream close()用法及代码示例
  13. 利用shell脚本来监控linux系统的负载与CPU占用情况
  14. 从零开始,我用了两年半逆袭秋招!
  15. 装载机液压系统原理图分析方法
  16. es文件浏览器鸿蒙,达人教你玩应用:ES文件浏览器之文件互传(原创首发)
  17. AndroidBLE--Measuring distance(测量距离)
  18. 钉钉机器人实现打卡提醒定时任务
  19. 「C#」Bitmap/Image.Save()报错“GDI+ 中发生一般性错误”的一个案例总结
  20. Git详解之六 Git工具

热门文章

  1. Spring Boot Redis 入门
  2. 图文讲解,团队开发中的 Git 最佳实践
  3. 应聘腾讯,面试官和我聊了一个小时的人生
  4. 「mysql优化专题」90%程序员面试都用得上的索引优化手册(5)【面试重点】
  5. 怎么样用idea上传git?-通俗易懂
  6. org.hibernate.NonUniqueObjectException 异常处理
  7. Address already in use: JVM_Bind 端口被占用解决办法
  8. vue后端框架mysql_springboot + vue 前后端结合·数据库查询
  9. linux 本地做yum源,linux——制作本地yum源
  10. java添加时间,如何通过Java中的addHours()方法添加时间