Windows身份验证,判断用户是不是对路线拥有访问权限

什么获得当前系统用户对文件/文件夹的操作权限?

开卷目录

细说ASP.NET Windows身份注脚

开卷目录

  • 开始
  • 认识ASP.NET
    Windows身份验证
  • 访问 Active
    Directory
  • 在ASP.NET中访问Active
    Directory
  • 行使Active
    Directory验证用户身份
  • 安然上下文与用户模拟
  • 在IIS中配备Windows身份验证
  • 至于浏览器的报到对话框难题
  • 在客户端代码中做客Windows身份注脚的页面

上篇博客自小编提及了1部分有关ASP.NET
Forms身份认证方面包车型大巴话题,这一次的博客将重视介绍ASP.NET Windows身份注解。

Forms身份认证尽管接纳大规模,然而,假设是在 Windows Active Directory
的条件中选择ASP.NET, 那么使用Windows身份验证也会比较方便。
方便性表现为:大家绝不再规划登录页面,不用编写登录验证逻辑。而且选取Windows身份验证会有更加好的平安全保卫持。

回去顶部

上篇博客自家说起了有的关于ASP.NET
Forms身份表明方面包车型大巴话题,这一次的博客将重大介绍ASP.NET Windows身份验证。

 1.得到安全音讯DirectorySecurity

DirectorySecurity fileAcl = Directory.GetAccessControl(folder);

通过Directory.GetAccessControl获取文件夹的权位/安全音讯

详见介绍,可参看MSDN官方文书档案)

对文本/文件夹权限的事无巨细操作,可参照一篇博客C#文件夹权限操作

  • 开始
  • 认识ASP.NET
    Windows身份认证
  • 访问 Active
    Directory
  • 在ASP.NET中访问Active
    Directory
  • 应用Active
    Directory验证用户地点
  • 有惊无险上下文与用户模拟
  • 在IIS中布置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。

地点二段话归纳了总结了三种身份认证方法的办事章程。
大家得以窥见它们存在以下差距: 一.
Forms地位验证必要Cookie表示登录状态,Windows身份认证则依靠于IIS 2.
Windows身份声明不要求大家设计登录页面,不用编写登录验证逻辑,由此更易于采纳。

在授权阶段,UrlAuthorizationModule依旧会依照当下用户检查将要访问的能源是还是不是获得许可。
接下来,FileAuthorizationModule检查 HttpContext.User.Identity 属性中的
IIdentity 对象是还是不是是 WindowsIdentity 类的一个实例。 如若 IIdentity
对象不是 WindowsIdentity 类的2个实例,则 FileAuthorizationModule
类甘休处理。 假诺存在 WindowsIdentity 类的1个实例,则
FileAuthorizationModule 类调用 AccessCheck Win32 函数(通过 P/Invoke)
来明确是否授权经过身份验证的客户端访问请求的公文。
如果该公文的安全描述符的自由访问控制列表 (DACL) 中至少含有三个 Read
访问控制项 (ACE),则允许该请求继续。 不然,FileAuthorizationModule
类调用 HttpApplication.CompleteRequest 方法并将情况码 40一 再次回到到客户端。

在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那三个与用户位置相关的指标。

重临顶部

Forms身份认证即使应用大规模,不过,就算是在 Windows Active Directory
的环境中选择ASP.NET, 那么使用Windows身份验证也会比较方便。
方便性表现为:大家绝不再规划登录页面,不用编写登录验证逻辑。而且采纳Windows身份验证会有越来越好的嘉峪关保险。

2. 获得文件夹访问权限列表FileSystemAccessRule

var rules = fileAcl.GetAccessRules(true, true,
typeof(System.Security.Principal.NTAccount)).OfType<FileSystemAccessRule>().ToList();

GetAccessRules()方法再次来到的是AuthorizationRule集合,此处只需求获得文件权限。

FileSystemAccessRule.aspx)继承自AuthorizationRule,并新增俩特本性

  • AccessControlType — 枚举 Allow/Deny
  • FileSystemRights —
    对文本的拜会权限详细音信(读/写等),可知上边列表: 

亚洲必赢官网 1亚洲必赢官网 2

 1   /// <summary>定义要创建访问和审核规则时使用的访问权限。</summary>
 2   [Flags]
 3   public enum FileSystemRights
 4   {
 5     ReadData = 1,
 6     ListDirectory = ReadData, // 0x00000001
 7     WriteData = 2,
 8     CreateFiles = WriteData, // 0x00000002
 9     AppendData = 4,
10     CreateDirectories = AppendData, // 0x00000004
11     ReadExtendedAttributes = 8,
12     WriteExtendedAttributes = 16, // 0x00000010
13     ExecuteFile = 32, // 0x00000020
14     Traverse = ExecuteFile, // 0x00000020
15     DeleteSubdirectoriesAndFiles = 64, // 0x00000040
16     ReadAttributes = 128, // 0x00000080
17     WriteAttributes = 256, // 0x00000100
18     Delete = 65536, // 0x00010000
19     ReadPermissions = 131072, // 0x00020000
20     ChangePermissions = 262144, // 0x00040000
21     TakeOwnership = 524288, // 0x00080000
22     Synchronize = 1048576, // 0x00100000
23     FullControl = Synchronize | TakeOwnership | ChangePermissions | ReadPermissions | Delete | WriteAttributes | ReadAttributes | DeleteSubdirectoriesAndFiles | Traverse | WriteExtendedAttributes | ReadExtendedAttributes | CreateDirectories | CreateFiles | ListDirectory, // 0x001F01FF
24     Read = ReadPermissions | ReadAttributes | ReadExtendedAttributes | ListDirectory, // 0x00020089
25     ReadAndExecute = Read | Traverse, // 0x000200A9
26     Write = WriteAttributes | WriteExtendedAttributes | CreateDirectories | CreateFiles, // 0x00000116
27     Modify = Write | ReadAndExecute | Delete, // 0x000301BF
28   }

View Code

 因为AuthorizationRule中,IdentityReference对应权限的用户/用户组标识,格式为:”MYDOMAIN\MyAccount”

故而,如通过当前系统用户名与IdentityReference相称,即可获取FileSystemAccessRule权限。如何得到用户名,见下一段落

上篇博客本身谈起了某些有关ASP.NET
Forms身份验证方面包车型客车话题,此番的博客将首要介绍ASP.NET Windows身份注解。

访问 Active Directory

我们平日使用LDAP协议来访问Active Directory, 在.net
framework中提供了DirectoryEntry和DirectorySearcher那二个体系让大家能够1本万利地从托管代码中访问
Active Directory 域服务。

只要大家要在”test.corp”那几个域中搜索有个别用户音信,大家能够动用上面包车型地铁语句构造3个DirectoryEntry对象:

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

在那段代码中,笔者利用硬编码的措施把域名写进了代码。
大家如何精晓当前计算机所利用的是哪个域名呢?
答案是:查看“笔者的微型总括机”的脾性对话框:

亚洲必赢官网 3

留意:这一个域名不自然与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的摸索。 大家得以行使下边包车型地铁步调来施行搜索: 一. 设置
DirectorySearcher.Filter 提示LDAP格式筛选器,这是二个字符串。 2.
频仍调用PropertiesToLoad.Add() 设置搜索进度中要摸索的性质列表。 三.
调用FindOne() 方法得到搜索结果。

下面包车型大巴代码演示了怎么从Active Directory中追寻登录名叫“fl四五”的用户新闻:

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());
    }
}

结果如下:

亚洲必赢官网 4

在后面包车型客车代码,我在搜索Active
Directory时,只搜索了”name,givenName,samaccountname,mail”那4天个性。
可是,LDAP还协助越来越多的品质,大家得以选拔上面包车型大巴代码查看越多的用户音信:亚洲必赢官网 5😉

        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
";

回去顶部

回到顶部

三. 收获当前系统用户名/用户组

因而 System.Environment.UserDomainName 和 System.Environment.UserName
取妥帖前用户名

对近年来系统用户名/用户组的其余操作,可参照

  • C# 管理 Windows
    本地用户组
  • C# 获取 Windows
    用户组成员

据此,将Path.Combine(Environment.UserDomainName,
Environment.UserName)与IdentityReference.Value相比,获取当前用户对文件夹的权能音讯

详尽完毕如下:

 1     /// <summary>
 2     /// 检查当前用户是否拥有此文件夹的操作权限
 3     /// </summary>
 4     /// <param name="folder"></param>
 5     /// <returns></returns>
 6     public static bool HasOperationPermission(string folder)
 7     {
 8         var currentUserIdentity = Path.Combine(Environment.UserDomainName, Environment.UserName);
 9 
10         DirectorySecurity fileAcl = Directory.GetAccessControl(folder);
11         var userAccessRules = fileAcl.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)).OfType<FileSystemAccessRule>().Where(i=>i.IdentityReference.Value==currentUserIdentity).ToList();
12 
13         return userAccessRules.Any(i => i.AccessControlType == AccessControlType.Deny);
14     }

 

Forms身份注明尽管应用大规模,可是,假若是在 Windows Active Directory
的环境中利用ASP.NET, 那么使用Windows身份认证也会相比便宜。
方便性表现为:大家不要再规划登录页面,不用编写登录验证逻辑。而且选取Windows身份认证会有更加好的自贡保持。

在ASP.NET中访问Active Directory

前面作者在三个控制台程序中示范了走访Active
Directory的点子,通过示范大家得以观望:在代码中,作者用Environment.UserName就足以收获当前用户的登录名。
不过,假若是在ASP.NET程序中,访问Environment.UserName就很有望得不到实在用户登录名。
因为:Environment.UserName是选择WIN3贰API中的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;
}

Windows身份验证,判断用户是不是对路线拥有访问权限。那正是说,大家得以选取这样的代码来获得所需的用户新闻:亚洲必赢官网 6😉

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中获取其它的用户信息,请参考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及较新版本的操作系统中才能正常运行。
        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>

程序运转的效益如下:

亚洲必赢官网 7

此外,还是能从Active
Directory查询叁个名字为memberof的属性(它与Windows用户组非亲非故),有时候能够用它有别于用户,设计与权力相关的操作。

在规划数据持久化的表结构时,由于此时从不“用户表”,那么咱们得以直接保存用户的登录名。
剩下的开销工作就与Forms身份认证未有太多的差距了。

回去顶部

认识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并创办1个包括FormsIdentity的GenericPrincipal对象,
然后把它赋值给HttpContext.User。

地方2段话归纳了席卷了二种身份认证方法的行事章程。
笔者们能够窥见它们存在以下差异:

  1. Forms身份验证需求Cookie表示登录情形,Windows身份认证则依靠于IIS
    贰.
    Windows身份认证不须要大家统一筹划登录页面,不用编写登录验证逻辑,因而更便于选择。

在授权阶段,UrlAuthorizationModule依旧会依照近日用户检查将要访问的财富是或不是获得许可。
接下来,FileAuthorizationModule检查 HttpContext.User.Identity 属性中的
IIdentity 对象是或不是是 WindowsIdentity 类的八个实例。 假设 IIdentity
对象不是 WindowsIdentity 类的2个实例,则 FileAuthorizationModule
类结束处理。 如果存在 WindowsIdentity 类的三个实例,则
FileAuthorizationModule 类调用 AccessCheck Win3二 函数(通过 P/Invoke)
来明显是或不是授权经过身份验证的客户端访问请求的文书。
借使该文件的平安描述符的即兴访问控制列表 (DACL) 中至少含有三个 Read
访问控制项 (ACE),则允许该请求继续。 不然,FileAuthorizationModule
类调用 HttpApplication.CompleteRequest 方法并将状态码 401 再次来到到客户端。

在Windows身份评释中,验证工作任重(Ren Zhong)而道远是由IIS达成的,WindowsAuthenticationModule其实只是肩负创设WindowsPrincipal和WindowsIdentity而已。
顺便介绍一下:Windows 身份验证又分为“NTLM 身份验证”和“Kerberos v伍身份验证”二种,
关于那二种Windows身份验证的越多说明可查看MSDN技术小说:释疑:ASP.NET
2.0 中的 Windows
身份验证。
在小编眼里,IIS最后采用哪一类Windows身份注脚形式并不影响大家的开发进度,因而本文不会谈论这些话题。

传说自己的实际上经验来看,使用Windows身份验证时,首要的成本工作将是基于登录名从Active
Directory获取用户消息。
因为,此时不要求大家再规划登录进程,IIS与ASP.NET已经为大家准备好了WindowsPrincipal和WindowsIdentity那二个与用户地方相关的对象。

重返顶部

回来顶部

动用Active Directory验证用户位置

日前介绍了ASP.NET
Windows身份验证,在那种艺术下,IIS和WindowsAuthenticationModule为我们实现了用户地方认证的进程。
可是,有时也许鉴于各个原因,须求大家以编制程序的情势选取Active
Directory验证用户身份,比如:在WinForm主次,或然别的的注脚逻辑。

咱俩不但能够从Active
Directory中查询用户消息,也足以用它来落到实处认证用户身份,这样便能够完成团结的报到验证逻辑。

无论是怎么行使Active
Directory,我们都急需选取DirectoryEntry和DirectorySearcher这3个目的。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);
    }
}

程序运转的职能如下:

亚洲必赢官网 8

回到顶部

访问 Active Directory

大家平时使用LDAP协议来访问Active Directory, 在.net
framework中提供了DirectoryEntry和DirectorySearcher那贰个品类让大家能够1本万利地从托管代码中访问
Active Directory 域服务。

只要大家要在”test.corp”这几个域中搜索某些用户新闻,大家能够使用上边包车型大巴语句构造3个DirectoryEntry对象:

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

在那段代码中,小编使用硬编码的主意把域名写进了代码。
咱俩什么知道当前电脑所运用的是哪位域名呢?
答案是:查看“作者的总结机”的习性对话框:

亚洲必赢官网 9

瞩目:那几个域名不必然与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格式筛选器,那是1个字符串。
  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());
    }
}

结果如下:

亚洲必赢官网 10

在眼前的代码,小编在搜索Active
Directory时,只搜索了”name,givenName,samaccountname,mail”那4个天性。
不过,LDAP还帮衬越来越多的习性,大家得以选取上边包车型大巴代码查看愈来愈多的用户新闻: 亚洲必赢官网 11

重临顶部

认识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)创制2个WindowsIdentity对象,Token通过调用context.WorkerRequest.GetUserToken()获得,
然后再依照WindowsIdentity 对象创立WindowsPrincipal对象,
然后把它赋值给HttpContext.User。

在Forms身份注解中,大家须要创制登录页面,让用户提交用户名和密码,然后检查用户名和密码的不错,
接下来创建1个含有FormsAuthenticationTicket对象的报到Cookie供后续请求使用。
FormsAuthenticationModule在ASP.NET管线的AuthenticateRequest事件中,
解析登录库克ie并创办1个饱含FormsIdentity的GenericPrincipal对象,
然后把它赋值给HttpContext.User。

上边二段话总结了归纳了三种身份申明方法的工作办法。
我们得以窥见它们存在以下差异: 一.
Forms地位认证要求Cookie表示登录意况,Windows身份表明则依靠于IIS 二.
Windows身份注明不须求大家统一筹划登录页面,不用编写登录验证逻辑,因而更便于接纳。

在授权阶段,UrlAuthorizationModule依然会基于当下用户检查将要访问的资源是或不是获得许可。
接下来,FileAuthorizationModule检查 HttpContext.User.Identity 属性中的
IIdentity 对象是还是不是是 WindowsIdentity 类的2个实例。 尽管 IIdentity
对象不是 WindowsIdentity 类的一个实例,则 FileAuthorizationModule
类结束处理。 要是存在 WindowsIdentity 类的贰个实例,则
FileAuthorizationModule 类调用 AccessCheck Win32 函数(通过 P/Invoke)
来鲜明是或不是授权经过身份验证的客户端访问请求的文本。
就算该公文的安全描述符的专断访问控制列表 (DACL) 中至少含有1个 Read
访问控制项 (ACE),则允许该请求继续。 不然,FileAuthorizationModule
类调用 HttpApplication.CompleteRequest 方法并将意况码 40一再次来到到客户端。 

在Windows身份认证中,验证工作首借使由IIS完成的,WindowsAuthenticationModule其实只是负责创立WindowsPrincipal和WindowsIdentity而已。
顺便介绍一下:Windows 身份验证又分为“NTLM 身份验证”和“Kerberos v5身份验证”三种,
关于那二种Windows身份注明的越来越多表明可查看MSDN技术小说:诠释:ASP.NET
二.0 中的 Windows
身份验证。
在小编看来,IIS最后选拔哪类Windows身份认证方法并不影响我们的开发进度,由此本文不会谈论这些话题。

依据自家的实际上经验来看,使用Windows身份注明时,首要的成本工作将是依照登录名从Active
Directory获取用户新闻。
因为,此时不必要大家再规划登录进程,IIS与ASP.NET已经为我们准备好了WindowsPrincipal和WindowsIdentity这1个与用户地方相关的靶子。

再次回到顶部

安全上下文与用户模拟

在ASP.NET
Windows身份认证环境中,与用户相关的雅安上下文对象保存在HttpContext.User属性中,是贰个门类为WindowsPrincipal的指标,
大家还足以访问HttpContext.User.Identity来得到经过身份认证的用户标识,它是三个WindowsIdentity类型的对象。

在.NET
Framework中,我们得以经过WindowsIdentity.GetCurrent()获取与当前线程相关的WindowsIdentity对象,
那种措施获得的是当下运作的Win3贰线程的广安上下文标识。
由于ASP.NET运转在IIS进度中,由此ASP.NET线程的平安标识其实是从IIS的进度中接二连三的,
所以此时用三种艺术获得的WindowsIdentity对象实际是不相同的。

在Windows操作系统中,许多权力检查皆以依照Win32线程的安全上下文标识,
于是前方所说的两种WindowsIdentity对象会促成编制程序模型的不1致难点,
为了缓解那几个题材,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,将见到如下图所示的结果:

亚洲必赢官网 12

方今修改一下web.config中设置:(只顾:前边加了一句配置

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

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

亚洲必赢官网 13

注明: 1. FISH-S凯雷德V2003是自小编的总计机名。它在2个未有域的条件中。 ②.
fish-li是本人的3个Windows帐号的登录名。 叁.
网址铺排在IIS陆中,进度以NETWO奥迪Q3K SE汉兰达VICE帐号运营。 4.
打开网页时,笔者输入的用户名是fish-li

前边2张图片的差别之处其实也便是ASP.NET的“模拟”所抒发的成效。

至于模拟,我想说4点: 1.
在ASP.NET中,大家相应访问HttpContext.User.Identity获取当前用户标识,那么就不设有有失常态态(此刻得以不要求效法),例如FileAuthorizationModule正是这么处理的。
二.
效仿只是在ASP.NET应用程序访问Windows系统财富时必要选用Windows的安检职能才会有用。

  1. Forms身份注明也能安顿模拟效用,但不得不模拟贰个Windows帐户。 肆.
    多数场所下是不须要效法的。

回到顶部

在ASP.NET中访问Active Directory

前方小编在2个控制台程序中示范了走访Active
Directory的章程,通过演示我们得以看到:在代码中,笔者用Environment.UserName就能够赢妥善前用户的登录名。
不过,假诺是在ASP.NET程序中,访问Environment.UserName就很有相当大恐怕得不到确实用户登录名。
因为:Environment.UserName是选拔WIN3二API中的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;
}

那就是说,大家得以动用那样的代码来获取所需的用户新闻: 亚洲必赢官网 14

使用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>

程序运维的效用如下:

亚洲必赢官网 15

其它,还足以从Active
Directory查询八个名字为memberof的质量(它与Windows用户组非亲非故),有时候能够用它有别于用户,设计与权力相关的操作。

在统一筹划数据持久化的表结构时,由于此时平昔不“用户表”,那么大家得以一贯保存用户的登录名。
剩下的开销工作就与Forms身份认证未有太多的出入了。

回到顶部

访问 Active Directory

小编们1般选取LDAP协议来访问Active Directory, 在.net
framework中提供了DirectoryEntry和DirectorySearcher那二个种类让大家得以便宜地从托管代码中走访
Active Directory 域服务。

比方大家要在”test.corp”那个域中搜索某些用户音信,我们能够动用上边包车型大巴语句构造一个DirectoryEntry对象:

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

在那段代码中,小编动用硬编码的不二秘籍把域名写进了代码。
大家怎么样领悟当前计算机所利用的是哪位域名呢?
答案是:查看“作者的微型计算机”的个性对话框:

亚洲必赢官网 16

留意:那个域名不肯定与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的搜索。 大家得以动用下边包车型地铁步子来施行搜索: 一. 装置
DirectorySearcher.Filter 提示LDAP格式筛选器,那是3个字符串。 2.
屡屡调用PropertiesToLoad.Add() 设置搜索进程中要物色的习性列表。 三.
调用FindOne() 方法得到搜索结果。

下面的代码演示了哪些从Active Directory中追寻登录名称为“fl四⑤”的用户消息:

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());
    }
}

结果如下:

亚洲必赢官网 17

在头里的代码,小编在搜索Active
Directory时,只搜索了”name,givenName,samaccountname,mail”那四性格子。
但是,LDAP还帮衬越来越多的质量,大家得以采纳上面包车型大巴代码查看越多的用户消息:
亚洲必赢官网 18

        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
";

回去顶部

在IIS中布局Windows身份验证

与运用Forms身份认证的程序不一样,使用Windows身份注明的顺序必要卓殊的配置步骤。
那一个小节将重点介绍在IIS中布署Windows身份认证,作者将常用的IIS陆和IIS7.伍为例分别介绍这几个安插。

IIS6的配置 请参考下图:

亚洲必赢官网 19

 

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

亚洲必赢官网 20

在意:Windows身份申明是必要设置的,方法请参考下图:

亚洲必赢官网 21

回来顶部

动用Active Directory验证用户身份

前面介绍了ASP.NET
Windows身份注明,在那种情势下,IIS和WindowsAuthenticationModule为大家达成了用户身份认证的进程。
但是,有时可能出于各类原因,必要大家以编制程序的方法接纳Active
Directory验证用户身份,比如:在WinForm先后,可能别的的注明逻辑。

大家不但能够从Active
Directory中询问用户新闻,也得以用它来促成认证用户地点,那样便足以兑现自身的报到验证逻辑。

不论是怎么着选取Active
Directory,大家都亟待利用DirectoryEntry和DirectorySearcher那2个对象。
DirectoryEntry还提供1个构造函数可让我们输入用户名和密码:

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

要落到实处本身的报到检查,就要求使用这几个构造函数。
以下是本身写用WinForm写的1个登录检查的示范:

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);
    }
}

程序运维的意义如下:

亚洲必赢官网 22

归来顶部

在ASP.NET中访问Active Directory

眼下笔者在3个控制台程序中示范了走访Active
Directory的章程,通过示范我们能够看看:在代码中,笔者用Environment.UserName就足以获取当前用户的登录名。
然则,如若是在ASP.NET程序中,访问Environment.UserName就很有非常大或者得不到实在用户登录名。
因为:Environment.UserName是应用WIN3二API中的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;
}

那正是说,我们能够动用那样的代码来博取所需的用户消息:
亚洲必赢官网 23

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中获取其它的用户信息,请参考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及较新版本的操作系统中才能正常运行。
        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>

程序运行的作用如下:

亚洲必赢官网 24

其它,还足以从Active
Directory查询一个号称memberof的习性(它与Windows用户组非亲非故),有时候能够用它有别于用户,设计与权力相关的操作。

在设计数据持久化的表结构时,由于此时从没有过“用户表”,那么我们能够直接保存用户的登录名。
剩下的支出工作就与Forms身份验证未有太多的反差了。

再次回到顶部

至于浏览器的报到对话框难点

当大家用浏览器访问贰个行使Windows身份评释的网址时,浏览器都会弹出贰个会话框(左IE,右Safari):

亚洲必赢官网 25

这时候,供给大家输入Windows的登录帐号,然后交到IIS验证身份。

第三次弹出那一个对话框很平常:因为程序要证实用户的身价。
可是,每一回关闭浏览器下次重新打开页面时,又会产出此对话框,此时感到就很不便利了。
就算有点浏览器能记住用户名和密码,但自己发现FireFox,Opera,Chrome还是会弹出那几个对话框,等待我们点击鲜明,
唯有Safari才不会干扰用户直接打开网页。IE的特别“记住笔者的密码”复选框完全是个摆放,它根本不会记住密码!

故此,笔者所试过的兼具浏览器中,唯有Safari是最人性化的。
即便在默许情况下,尽管IE不会铭记密码,每一趟都亟需再行输入。
不过,IE却得以支撑不提拔用户输入登录帐号而间接打开网页,此时IE将运用用户的当下Windows登录帐号传递给IIS验证身份。

要让IE打开一个Windows身份评释的网站不提示登录对话框,必须满意以下规则:

  1. 务必在 IIS 的 Web 站点属性中启用 Windows 集成身份验证。 二.
    客户端和Web服务器都必须在依照Microsoft Windows的平等个域内。 三. Internet
    Explorer 必须把所请求的 U奥迪Q7L 视为 Intranet(本地)。 4. Internet Explorer
    的 Intranet 区域的安全性设置必须设为“只在 Intranet 区域活动登录”。 5.
    请求Web页的用户必须拥有访问该Web页以及该Web页中援引的保有目的的贴切的文件系统(NTFS)权限。
  2. 用户必须用域帐号登录到Windows 。

在那多少个条件中,固然网址是在贰个Windows域中运作,除了第三条恐怕不满足外,其它条件应该都简单满意(第6条是默许值)。
因而,要让IE不提示输入登录帐号,只要确认保证第二条满足就能够了。
上边包车型大巴图纸演示了怎么着做到那一个布局:(注意:配置格局也适合用域名访问的气象)

亚洲必赢官网 26

 

其余,除了在IE中装置Intranet外,仍是能够在做客网址时,用电脑名代替IP地址或许域名
那么IE始终认为是在做客Intranet内的网址,此时也不会弹出登录对话框。

在此,小编想再啰嗦3句: 一.
IE在集成Windows身份注解时,纵然不晋升登录对话框,可是不代表不安全,它会自行传送登录凭据。
二.
那种表现唯有IE才能帮忙。(其余的浏览器只是会铭记密码,在达成上实在是不等同的。)

  1. 集成Windows身份验证,也只适合在Intranet的条件中使用。

归来顶部

有惊无险上下文与用户模拟

在ASP.NET
Windows身份申明环境中,与用户相关的平安上下文对象保存在HttpContext.User属性中,是贰个种类为WindowsPrincipal的靶子,
大家还能够访问HttpContext.User.Identity来获取经过身份验证的用户标识,它是2个WindowsIdentity类型的目的。

在.NET
Framework中,我们得以透过WindowsIdentity.GetCurrent()获取与当前线程相关的WindowsIdentity对象,
那种方式赢得的是现阶段运作的Win3二线程的平安上下文标识。
由于ASP.NET运营在IIS进度中,由此ASP.NET线程的鄂州标识其实是从IIS的经过中延续的,
所以此时用两种格局赢得的WindowsIdentity对象实际是例外的。

在Windows操作系统中,许多权力检查都以根据Win3二线程的含笑花上下文标识,
于是如今所说的二种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,将看到如下图所示的结果:

亚洲必赢官网 27

前日涂改一下web.config中装置:(留神:后边加了一句配置

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

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

亚洲必赢官网 28

说明:

  1. FISH-SMuranoV200三是自家的计量机名。它在二个未有域的环境中。
  2. fish-li是自己的三个Windows帐号的登录名。
  3. 网址铺排在IIS陆中,进度以NETWOTiggoK SE奥迪Q三VICE帐号运营。
  4. 开辟网页时,小编输入的用户名是fish-li

眼下贰张图纸的差别之处其实相当于ASP.NET的“模拟”所表明的作用。

有关模拟,笔者想说肆点:
一.
在ASP.NET中,大家理应访问HttpContext.User.Identity获取当前用户标识,那么就不存在难题(那儿得以不需求效法),例如FileAuthorizationModule正是那般处理的。
二.
模拟只是在ASP.NET应用程序访问Windows系统财富时索要采用Windows的保山检查职能才会有用。

  1. Forms身份认证也能安顿模拟功效,但不得不模拟3个Windows帐户。
  2. 绝大部分动静下是不要求效法的。

归来顶部

应用Active Directory验证用户地方

前方介绍了ASP.NET
Windows身份认证,在那种措施下,IIS和WindowsAuthenticationModule为我们落实了用户地方验证的长河。
然则,有时大概鉴于各类缘由,供给大家以编制程序的办法采纳Active
Directory验证用户地方,比如:在WinForm先后,大概其余的印证逻辑。

咱俩不光能够从Active
Directory中询问用户音讯,也可以用它来贯彻认证用户身份,那样便得以兑现协调的登录验证逻辑。

不管是怎么着运用Active
Directory,我们都急需使用DirectoryEntry和DirectorySearcher那一个对象。
DirectoryEntry还提供1个构造函数可让大家输入用户名和密码:

// 摘要:
//     初始化 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);
    }
}

程序运维的功力如下:

亚洲必赢官网 29

回到顶部

在客户端代码中走访Windows身份验证的页面

在上篇博客中,笔者出现说法了怎么着用代码访问二个施用Forms身份验证的网址中的受限页面,方法是采用CookieContainer对象收取服务端生的登录Cookie。
然则,在Windows身份注明的网址中,身份验证的进度产生在IIS中,而且一向不行使库克ie保存登录状态,而是须要在乞求时发送要求的身份验证消息。

在选用代码做为客户端访问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,代码中的三种艺术是有效的。
那二种格局的差距: 壹. Credentials = CredentialCache.DefaultCredentials;
表示在出殡和埋葬请求会带上圈套前用户的身份验证凭据。 ②. UseDefaultCredentials =
true; 此方法在里面会调用前边的章程,因而与前面包车型大巴措施是同等的。 三.
Credentials = CredentialCache.DefaultNetworkCredentials; 是在.NET
二.0中援引的新措施。

至于DefaultCredentials和DefaultNetworkCredentials的愈多差异,请看本身整理的报表:

Credentials属性

评释类型

实例类型

.NET帮忙版本

DefaultCredentials

ICredentials

SystemNetworkCredential

从1.0开始

DefaultNetworkCredentials

NetworkCredential

SystemNetworkCredential

从2.0开始

四个门类的一连关系: 1. NetworkCredential完毕了ICredentials接口, 二.
SystemNetworkCredential继承自NetworkCredential。

 

在终结那篇博客在此之前,笔者想作者应当谢谢新蛋。
在新蛋的互联网环境中,让笔者学会了选用Windows身份验证。
除了感激之外,笔者以往还专程挂念 fl四5 那些登录名……

在IIS中配置Windows身份认证

与使用Forms身份注解的次序区别,使用Windows身份验证的次第要求十分的布局步骤。
这几个小节将重大介绍在IIS中配备Windows身份申明,小编将常用的IIS六和IIS7.伍为例分别介绍这一个配置。

IIS6的配置 请参考下图:

亚洲必赢官网 30

 

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

亚洲必赢官网 31

专注:Windows身份认证是亟需设置的,方法请参考下图:

亚洲必赢官网 32

回到顶部

乌海上下文与用户模拟

在ASP.NET
Windows身份验证环境中,与用户相关的天水上下文对象保存在HttpContext.User属性中,是三个连串为WindowsPrincipal的对象,
我们还可以访问HttpContext.User.Identity来获得经过身份验证的用户标识,它是1个WindowsIdentity类型的靶子。

在.NET
Framework中,大家得以经过WindowsIdentity.GetCurrent()获取与当前线程相关的WindowsIdentity对象,
那种措施赢得的是当下运作的Win3二线程的汉中上下文标识。
由于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,将看到如下图所示的结果:

亚洲必赢官网 33

现行反革命涂改一下web.config中设置:(留神:前边加了一句配置

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

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

亚洲必赢官网 34

评释: 1. FISH-S途观V2003是本身的盘算机名。它在三个没有域的环境中。 ②.
fish-li是小编的1个Windows帐号的登录名。 3.
网站安插在IIS陆中,进度以NETWO奥迪Q7K SE安德拉VICE帐号运营。 肆.
打开网页时,小编输入的用户名是fish-li

前方2张图纸的差异之处其实也即是ASP.NET的“模拟”所发布的法力。

有关模拟,笔者想说4点: 一.
在ASP.NET中,我们相应访问HttpContext.User.Identity获取当前用户标识,那么就不存在难点(那时能够不供给效法),例如FileAuthorizationModule就是如此处理的。
二.
模拟只是在ASP.NET应用程序访问Windows系统能源时索要采用Windows的安检功用才会有用。

  1. Forms身份注脚也能安顿模拟成效,但只好模拟3个Windows帐户。 四.
    半数以上情状下是不要求效法的。

回到顶部

关于浏览器的报到对话框难题

当大家用浏览器访问四个应用Windows身份验证的网站时,浏览器都会弹出一个会话框(左IE,右Safari):

亚洲必赢官网 35

那儿,供给我们输入Windows的登录帐号,然后交到IIS验证身份。

第二回弹出那些对话框很正规:因为程序要证实用户的地点。
可是,每趟关闭浏览器下次再度打开页面时,又会并发此对话框,此时感觉到就很不方便人民群众了。
就算如此有点浏览器能记住用户名和密码,但本身发觉Fire福克斯,Opera,Chrome依然会弹出那个对话框,等待大家点击分明,
只有Safari才不会纷扰用户一贯打开网页。
IE的尤其“记住本身的密码”复选框完全是个安置,它根本不会铭记密码!

故此,小编所试过的兼具浏览器中,唯有Safari是最人性化的。
即使在暗中同意境况下,即使IE不会铭记密码,每回都亟需再度输入。
不过,IE却能够支撑不提示用户输入登录帐号而直白打开网页, 此时IE将动用用户的当下Windows登录帐号传递给IIS验证身份。

要让IE打开一个Windows身份认证的网址不提醒登录对话框,必须满意以下条件:

  1. 务必在 IIS 的 Web 站点属性中启用 Windows 集成身份验证。
  2. 客户端和Web服务器都必须在依据Microsoft Windows的同等个域内。
  3. Internet Explorer 必须把所请求的 UPAJEROL 视为 Intranet(当地)。
  4. Internet Explorer 的 Intranet 区域的安全性设置必须设为“只在 Intranet
    区域自动登录”。
    5.
    伸手Web页的用户必须拥有访问该Web页以及该Web页中引用的持有指标的适用的文件系统(NTFS)权限。
  5. 用户必须用域帐号登录到Windows 。

在那多少个标准中,假设网站是在多少个Windows域中运营,除了第二条可能不满足外,其余条件应该都简单满足(第5条是默许值)。
由此,要让IE不提醒输入登录帐号,只要确认保证第一条知足就足以了。
下边包车型客车图形演示了哪些完结那几个布局:(注意:配置方式也符合用域名访问的情事)

亚洲必赢官网 36

 

其它,除了在IE中安装Intranet外,还是能够在做客网址时,用计算机名代替IP地址也许域名
那么IE始终认为是在做客Intranet内的网址,此时也不会弹出登录对话框。

在此,笔者想再啰嗦叁句:
一.
IE在集成Windows身份注明时,固然不提醒登录对话框,不过不意味不安全,它会自行传送登录凭据。
二.
那种表现唯有IE才能支持。(其余的浏览器只是会铭记密码,在促成上其实是差异的。)

  1. 集成Windows身份认证,也只适合在Intranet的条件中选拔。

回到顶部

在IIS中布局Windows身份验证

与行使Forms身份验证的主次分裂,使用Windows身份认证的次序须要十分的布置步骤。
这么些小节将重点介绍在IIS中配置Windows身份认证,作者将常用的IIS陆和IIS七.五为例分别介绍那一个计划。

IIS6的配置 请参考下图:

亚洲必赢官网 37

 

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

亚洲必赢官网 38

瞩目:Windows身份表明是必要安装的,方法请参见下图:

亚洲必赢官网 39

回去顶部

在客户端代码中做客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;
    此方法在里面会调用后面包车型大巴情势,因而与前方的方法是1致的。
  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 那几个登录名……

转自:

关于浏览器的记名对话框难点

当大家用浏览器访问3个选用Windows身份验证的网址时,浏览器都会弹出多少个对话框(左IE,右Safari):

亚洲必赢官网 40

此时,要求大家输入Windows的报到帐号,然后交由IIS验证身份。

第2遍弹出这一个对话框很健康:因为程序要验证用户的身价。
不过,每一遍关闭浏览器下次再也打开页面时,又会现出此对话框,此时觉得就很不便宜了。
固然有个别浏览器能记住用户名和密码,但笔者意识FireFox,Opera,Chrome依然会弹出这些对话框,等待我们点击分明,
只有Safari才不会扰乱用户一向打开网页。
IE的不得了“记住自个儿的密码”复选框完全是个安放,它根本不会铭记密码!

就此,作者所试过的拥有浏览器中,唯有Safari是最人性化的。
纵然在暗中同意景况下,尽管IE不会记住密码,每一次都急需再度输入。
可是,IE却足以帮衬不提示用户输入登录帐号而一贯打开网页,
此时IE将应用用户的脚下Windows登录帐号传递给IIS验证身份。

要让IE打开三个Windows身份验证的网址不升迁登录对话框,必须知足以下条件:

  1. 总得在 IIS 的 Web 站点属性中启用 Windows 集成身份验证。 贰.
    客户端和Web服务器都不可能不在依照Microsoft Windows的壹模一样个域内。 3. Internet
    Explorer 必须把所请求的 U纳瓦拉L 视为 Intranet(本地)。 肆. Internet Explorer
    的 Intranet 区域的安全性设置必须设为“只在 Intranet 区域自动登录”。 5.
    请求Web页的用户必须具有访问该Web页以及该Web页中引用的全数指标的合适的文件系统(NTFS)权限。
  2. 用户必须用域帐号登录到Windows 。

在那多少个规格中,如果网站是在2个Windows域中运营,除了第三条也许不满足外,其余条件应该都简单满足(第5条是暗中同意值)。
由此,要让IE不提醒输入登录帐号,只要确定保障第一条满意就足以了。
上面包车型客车图形演示了怎么着实现那一个布局:(注意:配置格局也切合用域名访问的场所)

亚洲必赢官网 41

 

除此以外,除了在IE中设置Intranet外,还是能够在造访网址时,亚洲必赢官网,用微型计算机名代替IP地址大概域名
那么IE始终认为是在造访Intranet内的网址,此时也不会弹出登录对话框。

在此,作者想再啰嗦叁句: 一.
IE在集成Windows身份认证时,纵然不升迁登录对话框,可是不意味不安全,它会自动传送登录凭据。
贰.
那种作为唯有IE才能扶助。(此外的浏览器只是会铭记密码,在贯彻上其实是不壹样的。)

  1. 集成Windows身份评释,也只适合在Intranet的条件中动用。

再次来到顶部

在客户端代码中走访Windows身份验证的页面

在上篇博客中,笔者出现说法了怎么用代码访问2个施用Forms身份验证的网址中的受限页面,方法是利用CookieContainer对象收取服务端生的报到Cookie。
不过,在Windows身份评释的网址中,身份验证的进度爆发在IIS中,而且根本不选取库克ie保存登录状态,而是供给在乞求时发送须要的身份验证新闻。

在应用代码做为客户端访问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;
表示在出殡和埋葬请求会带上当前用户的身份验证凭据。 二. UseDefaultCredentials =
true; 此方法在其间会调用前边的不二等秘书诀,因而与前方的格局是同样的。 三.
Credentials = CredentialCache.DefaultNetworkCredentials; 是在.NET
二.0中引用的新情势。

关于DefaultCredentials和DefaultNetworkCredentials的更加多差异,请看本人收拾的表格:

Credentials属性

表明类型

实例类型

.NET援救版本

DefaultCredentials

ICredentials

SystemNetworkCredential

从1.0开始

DefaultNetworkCredentials

NetworkCredential

SystemNetworkCredential

从2.0开始

多少个类型的接续关系: 一. NetworkCredential完成了ICredentials接口, 二.
SystemNetworkCredential继承自NetworkCredential。

 

在终止那篇博客在此以前,笔者想作者应当感谢新蛋。
在新蛋的互连网环境中,让自个儿学会了采取Windows身份认证。
除了感激之外,作者今日还特地怀想 fl四伍 那几个登录名……

 

点击那里下载示例代码

网站地图xml地图