威尼斯人线上娱乐

【威尼斯人线上娱乐】看清用户是或不是对路线拥有访问权限,Windows身份认证

7 4月 , 2019  

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

翻阅目录

细说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
Forms身份注解方面包车型地铁话题,此次的博客将注重介绍ASP.NET Windows身份验证。

 壹.到手安全音讯DirectorySecurity

DirectorySecurity fileAcl = Directory.GetAccessControl(folder);

经过Directory.GetAccessControl获取文件夹的权位/安全新闻

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

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

  • 开始
  • 【威尼斯人线上娱乐】看清用户是或不是对路线拥有访问权限,Windows身份认证。认识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身份注明在广大基础方面是1律的。上篇博客我说过:自笔者认为ASP.NET的地点申明的最中央部分其实正是HttpContext.User那天性子所针对的指标。在接下去的有些,小编将重大分析那一个指标在三种身份认证中有怎么样异样。

在ASP.NET身份验证进程中,IPrincipal和IIdentity那二个接口有着拾分首要的效劳。
前者定义用户对象的基本作用,后者定义标识对象的基本效率,
差异的身价验证方法得到的那1个接口的实例也是例外的。

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

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

上边二段话归纳了归纳了二种身份申明形式的办事办法。
大家能够发现它们存在以下差别: 1.
Forms地方认证要求Cookie表示登录意况,Windows身份注解则依靠于IIS 二.
Windows身份验证不须要我们设计登录页面,不用编写登录验证逻辑,因而更易于选用。

在授权阶段,UrlAuthorizationModule还是会基于当下用户检查将要访问的能源是不是获得许可。
接下来,FileAuthorizationModule检查 HttpContext.User.Identity 属性中的
IIdentity 对象是或不是是 WindowsIdentity 类的二个实例。 假若 IIdentity
对象不是 WindowsIdentity 类的3个实例,则 FileAuthorizationModule
类甘休处理。 如果存在 WindowsIdentity 类的二个实例,则
FileAuthorizationModule 类调用 AccessCheck Win3二 函数(通过 P/Invoke)
来分明是还是不是授权经过身份验证的客户端访问请求的公文。
假使该文件的安全描述符的轻易访问控制列表 (DACL) 中至少含有3个 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这么些与用户地方相关的对象。

重临顶部

Forms身份表明即便选拔大规模,不过,借使是在 Windows Active Directory
的环境中使用ASP.NET, 那么使用Windows身份申明也会比较方便。
方便性表现为:大家绝不再规划登录页面,不用编写登录验证逻辑。而且动用Windows身份申明会有更加好的安全保持。

贰. 拿走文件夹访问权限列表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权限。怎么样赢得用户名,见下1段落

上篇博客本身聊到了有些关于ASP.NET
Forms身份注脚方面包车型大巴话题,这一次的博客将重点介绍ASP.NET Windows身份验证。

访问 Active Directory

咱俩壹般选用LDAP协议来访问Active Directory, 在.net
framework中提供了DirectoryEntry和DirectorySearcher那三个项目让我们得以便宜地从托管代码中走访
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格式筛选器,那是多少个字符串。 二.
往往调用PropertiesToLoad.Add() 设置搜索进度中要寻找的习性列表。 三.
调用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());
    }
}

结果如下:

威尼斯人线上娱乐 4

在头里的代码,笔者在搜索Active
Directory时,只搜索了”name,givenName,samaccountname,mail”那七个属性。
但是,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

前边作者在1个控制台程序中示范了访问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;
}

那就是说,大家得以行使这样的代码来博取所需的用户音讯:威尼斯人线上娱乐 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查询1个名叫memberof的性质(它与Windows用户组非亲非故),有时候能够用它有别于用户,设计与权力相关的操作。

在设计数据持久化的表结构时,由于此时未有“用户表”,那么大家得以一向保存用户的登录名。
剩下的支出工作就与Forms身份认证没有太多的差距了。

重临顶部

认识ASP.NET Windows身份验证

要选拔Windows身份注明形式,须要在web.config设置:

<authentication mode="Windows" />

Windows身份申明做为ASP.NET的默许认证格局,与Forms身份验证在重重基础方面是同壹的。 上篇博客我说过:小编觉得ASP.NET的身价验证的最核心部分其实正是HttpContext.User这几个天性所针对的靶子。 在接下去的壹些,笔者将根本分析那个目的在三种身份注脚中有怎么着差别。

在ASP.NET身份注解进度中,IPrincipal和IIdentity那2个接口有着尤其关键的机能。
前者定义用户对象的基本效能,后者定义标识对象的基本作用,
分化的地方注明格局赢得的那二个接口的实例也是见仁见智的。

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

在Forms身份认证中,大家须要创立登录页面,让用户提交用户名和密码,然后检查用户名和密码的正确性,
接下来创造2个涵盖FormsAuthenticationTicket对象的登录Cookie供后续请求使用。
FormsAuthenticationModule在ASP.NET管线的AuthenticateRequest事件中,
解析登录库克ie并创设1个带有FormsIdentity的GenericPrincipal对象,
然后把它赋值给HttpContext.User。

地方二段话回顾了包括了两种身份验证方式的做事办法。
咱俩得以窥见它们存在以下差距:

  1. Forms身份注脚供给Cookie表示登录状态,Windows身份认证则凭借于IIS
    二.
    Windows身份认证不供给大家陈设登录页面,不用编写登录验证逻辑,因而更便于选取。

在授权阶段,UrlAuthorizationModule依然会根据近年来用户检查将要访问的能源是不是得到许可。
接下来,FileAuthorizationModule检查 HttpContext.User.Identity 属性中的
IIdentity 对象是还是不是是 WindowsIdentity 类的3个实例。 假如 IIdentity
对象不是 WindowsIdentity 类的3个实例,则 FileAuthorizationModule
类停止处理。 如果存在 WindowsIdentity 类的多个实例,则
FileAuthorizationModule 类调用 AccessCheck Win3二 函数(通过 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那3个与用户地方相关的对象。

回到顶部

重临顶部

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

程序运营的成效如下:

威尼斯人线上娱乐 8

回去顶部

访问 Active Directory

作者们普通采纳LDAP协议来访问Active Directory, 在.net
framework中提供了DirectoryEntry和DirectorySearcher这一个连串让我们能够方便地从托管代码中走访
Active Directory 域服务。

若果我们要在”test.corp”那个域中搜索有些用户消息,大家能够动用上边的语句构造三个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”那四特性情。
然则,LDAP还支持越来越多的习性,大家得以行使下边包车型客车代码查看越来越多的用户音信: 威尼斯人线上娱乐 11

回到顶部

认识ASP.NET Windows身份验证

要使用Windows身份注解方式,必要在web.config设置:

<authentication mode="Windows" />

Windows身份注明做为ASP.NET的默许认证方法,与Forms身份验证在不少基础方面是1致的。
上篇博客我说过:自家觉得ASP.NET的身价验证的最宗旨部分其实便是HttpContext.User那特性情所指向的对象。
在接下去的局地,小编将主要分析那几个目的在三种身份验证中有何样差距。

在ASP.NET身份注解进度中,IPrincipal和IIdentity那一个接口有着十二分重大的成效。
前者定义用户对象的基本成效,后者定义标识对象的基本功用,
分化的地位表明方法获得的那2个接口的实例也是见仁见智的。

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 二.
Windows身份声明不需求大家统一筹划登录页面,不用编写登录验证逻辑,由此更便于采用。

在授权阶段,UrlAuthorizationModule如故会基于当下用户检查将要访问的能源是还是不是拿到许可。
接下来,FileAuthorizationModule检查 HttpContext.User.Identity 属性中的
IIdentity 对象是或不是是 WindowsIdentity 类的多少个实例。 如若 IIdentity
对象不是 WindowsIdentity 类的一个实例,则 FileAuthorizationModule
类结束处理。 假如存在 WindowsIdentity 类的二个实例,则
FileAuthorizationModule 类调用 AccessCheck Win3贰 函数(通过 P/Invoke)
来显著是否授权经过身份验证的客户端访问请求的文本。
假使该公文的安全描述符的人身自由访问控制列表 (DACL) 中至少含有1个 Read
访问控制项 (ACE),则允许该请求继续。 不然,FileAuthorizationModule
类调用 HttpApplication.CompleteRequest 方法并将景况码 401重回到客户端。 

在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那3个与用户位置相关的对象。

回到顶部

中卫上下文与用户模拟

在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对象会造成编程模型的不均等难题,
为了缓解这几个难点,ASP.NET提供了“模拟”功能,允许线程以特定的Windows帐户的平安上下文来访问能源。

为了能越来越好的精通模拟的效能,小编准备了3个演示(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奥迪Q7V200三是本人的盘算机名。它在3个未有域的条件中。 二.
fish-li是自家的一个Windows帐号的登录名。 3.
网址安顿在IIS陆中,进度以NETWO君越K SE奥迪Q7VICE帐号运维。 四.
开辟网页时,笔者输入的用户名是fish-li

日前贰张图片的反差之处其实也等于ASP.NET的“模拟”所表明的成效。

关于模拟,作者想说四点: 1.
在ASP.NET中,我们应当访问HttpContext.User.Identity获取当前用户标识,那么就不设有失常态(此时能够不要求效法),例如FileAuthorizationModule正是那样处理的。
二.
效仿只是在ASP.NET应用程序访问Windows系统财富时需求选择Windows的海东检查作用才会有用。

  1. Forms身份申明也能配备模拟功效,但不得不模拟贰个Windows帐户。 四.
    超越3/陆景况下是不要求效法的。

回到顶部

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

那正是说,大家得以行使那样的代码来取得所需的用户消息: 威尼斯人线上娱乐 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

咱俩司空见惯使用LDAP协议来访问Active Directory, 在.net
framework中提供了DirectoryEntry和DirectorySearcher这个连串让大家能够壹本万利地从托管代码中访问
Active Directory 域服务。

设若大家要在”test.corp”这几个域中搜索有个别用户音信,大家能够使用上边的语句构造3个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格式筛选器,那是多个字符串。 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”这5个属性。
但是,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六和IIS柒.5为例分别介绍那一个配置。

IIS6的配置 请参考下图:

威尼斯人线上娱乐 19

 

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

威尼斯人线上娱乐 20

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

威尼斯人线上娱乐 21

回到顶部

动用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写的3个登录检查的示范:

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

日前作者在二个控制台程序中示范了拜访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身份验证未有太多的歧异了。

回到顶部

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

当大家用浏览器访问2个选用Windows身份注明的网站时,浏览器都会弹出2个对话框(左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 必须把所请求的 URubiconL 视为 Intranet(当地)。 肆. Internet Explorer
    的 Intranet 区域的安全性设置必须设为“只在 Intranet 区域自动登录”。 五.
    请求Web页的用户必须有所访问该Web页以及该Web页中援引的兼具指标的稳妥的文件系统(NTFS)权限。
  2. 用户必须用域帐号登录到Windows 。

在那多少个条件中,倘若网址是在四个Windows域中运营,除了第1条只怕不满足外,别的条件应该都不难满足(第伍条是暗中同意值)。
因而,要让IE不提醒输入登录帐号,只要确定保证第贰条满意就足以了。
下边包车型大巴图片演示了如何形成那个布局:(注意:配置情势也符合用域名访问的处境)

威尼斯人线上娱乐 26

 

别的,除了在IE中安装Intranet外,还是可以在访问网址时,用总括机名代替IP地址大概域名
那么IE始终认为是在访问Intranet内的网址,此时也不会弹出登录对话框。

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

  1. 集成Windows身份注解,也只适合在Intranet的条件中采纳。

回去顶部

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

在ASP.NET
Windows身份验证环境中,与用户相关的日喀则上下文对象保存在HttpContext.User属性中,是3个项目为WindowsPrincipal的对象,
大家还是能够访问HttpContext.User.Identity来收获经过身份验证的用户标识,它是一个WindowsIdentity类型的靶子。

在.NET
Framework中,大家得以由此WindowsIdentity.GetCurrent()获取与当下线程相关的WindowsIdentity对象,
那种措施取得的是如今运维的Win32线程的固原上下文标识。
由于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-S途胜V200叁是自家的总结机名。它在二个未有域的条件中。
  2. fish-li是自我的叁个Windows帐号的登录名。
  3. 网址布置在IIS陆中,进程以NETWO中华VK SE凯雷德VICE帐号运营。
  4. 开拓网页时,笔者输入的用户名是fish-li

如今二张图片的异样之处其实也正是ASP.NET的“模拟”所发挥的功力。

有关模拟,作者想说四点:
1.
在ASP.NET中,大家相应访问HttpContext.User.Identity获取当前用户标识,那么就不存在难题(此时能够不须求效法),例如FileAuthorizationModule正是那般处理的。
二.
模拟只是在ASP.NET应用程序访问Windows系统财富时索要运用Windows的平安全检查查功能才会有用。

  1. Forms身份验证也能安顿模拟效用,但只好模拟一个Windows帐户。
  2. 多数意况下是不须要效法的。

回来顶部

利用Active Directory验证用户地点

眼下介绍了ASP.NET
Windows身份注明,在那种格局下,IIS和WindowsAuthenticationModule为大家完成了用户地方认证的进度。
可是,有时只怕鉴于各样缘由,供给大家以编程的方法采取Active
Directory验证用户地点,比如:在WinForm主次,或许其它的印证逻辑。

咱俩不但能够从Active
Directory中查询用户新闻,也得以用它来落到实处认证用户身份,那样便足以兑现团结的报到验证逻辑。

甭管是哪些采纳Active
Directory,我们都急需动用DirectoryEntry和DirectorySearcher这个目的。
DirectoryEntry还提供3个构造函数可让我们输入用户名和密码:

// 摘要:
//     初始化 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对象吸收服务端生的记名库克ie。
但是,在Windows身份认证的网址中,身份验证的经过发生在IIS中,而且根本不行使库克ie保存登录意况,而是须要在伸手时发送供给的身份验证新闻。

在运用代码做为客户端访问Web服务器时,大家照例必要选用HttpWebRequest对象。
为了能让HttpWebRequest在拜访IIS时发送供给的身份验证音讯,HttpWebRequest提供1个属性都得以做到那么些效能:

// 获取或设置请求的身份验证信息。
//
// 返回结果:
//     包含与该请求关联的身份验证凭据的 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; 此方法在里边会调用前面包车型的士秘籍,由此与日前的章程是均等的。 三.
Credentials = CredentialCache.DefaultNetworkCredentials; 是在.NET
二.0中引用的新办法。

至于DefaultCredentials和DefaultNetworkCredentials的越多差距,请看自个儿整理的表格:

Credentials属性

注脚类型

实例类型

.NET扶助版本

DefaultCredentials

ICredentials

SystemNetworkCredential

从1.0开始

DefaultNetworkCredentials

NetworkCredential

SystemNetworkCredential

从2.0开始

多个项指标接轨关系: 一. NetworkCredential完结了ICredentials接口, 2.
SystemNetworkCredential继承自NetworkCredential。

 

在收尾那篇博客在此之前,作者想笔者应当谢谢新蛋。
在新蛋的互联网环境中,让本身学会了动用Windows身份注明。
除了谢谢之外,笔者前些天还特地记念 fl四伍 这几个登录名……

在IIS中布置Windows身份验证

与运用Forms身份认证的主次差异,使用Windows身份注脚的次序须求万分的陈设步骤。
这几个小节将第二介绍在IIS中安排Windows身份认证,我将常用的IIS六和IIS7.五为例分别介绍这一个布置。

IIS6的配置 请参考下图:

威尼斯人线上娱乐 30

 

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

威尼斯人线上娱乐 31

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

威尼斯人线上娱乐 32

回来顶部

平安上下文与用户模拟

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

在.NET
Framework中,大家得以因而WindowsIdentity.GetCurrent()获取与当下线程相关的WindowsIdentity对象,
那种情势取得的是眼前运作的Win32线程的平安上下文标识。
由于ASP.NET运转在IIS进度中,因而ASP.NET线程的鄂州标识其实是从IIS的经过中一而再的,
所以此时用二种方法取得的WindowsIdentity对象实际是例外的。

在Windows操作系统中,许多权力检查都以基于Win3贰线程的新余上下文标识,
于是前边所说的三种WindowsIdentity对象会导致编制程序模型的不雷同难题,
为了消除那几个难题,ASP.NET提供了“模拟”功效,允许线程以特定的Windows帐户的安全上下文来访问资源。

为了能更加好的精晓模拟的作用,作者准备了2个演示(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

证实: 一. FISH-S普拉多V200三是本人的盘算机名。它在1个未有域的条件中。 二.
fish-li是本人的3个Windows帐号的登录名。 三.
网址安顿在IIS陆中,进程以NETWO奥迪Q7K SESportageVICE帐号运营。 四.
开辟网页时,笔者输入的用户名是fish-li

前面二张图片的距离之处其实也正是ASP.NET的“模拟”所抒发的效果。

至于模拟,作者想说肆点: ①.
在ASP.NET中,我们理应访问HttpContext.User.Identity获取当前用户标识,那么就不设不经常(那时候得以不须要效法),例如FileAuthorizationModule就是如此处理的。
二.
模拟只是在ASP.NET应用程序访问Windows系统能源时索要利用Windows的拉萨检查作用才会有用。

  1. Forms身份表明也能布署模拟效能,但只可以模拟3个Windows帐户。 四.
    大多数境况下是不要求效法的。

重回顶部

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

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

威尼斯人线上娱乐 35

那时候,须求大家输入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 必须把所请求的 UPAJEROL 视为 Intranet(本地)。
  4. Internet Explorer 的 Intranet 区域的安全性设置必须设为“只在 Intranet
    区域自动登录”。
    5.
    请求Web页的用户必须怀有访问该Web页以及该Web页中援引的兼具指标的妥当的文件系统(NTFS)权限。
  5. 用户必须用域帐号登录到Windows 。

在那多少个标准中,要是网站是在1个Windows域中运维,除了第二条只怕不满足外,其它条件应该都容易满意(第6条是暗中认可值)。
由此,要让IE不提示输入登录帐号,只要确认保证第三条满意就足以了。
上边包车型地铁图形演示了哪些完毕那一个布局:(注意:配置情势也合乎用域名访问的情事)

威尼斯人线上娱乐 36

 

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

在此,作者想再啰嗦三句:
一.
IE在集成Windows身份验证时,就算不提醒登录对话框,然则不意味不安全,它会自动传送登录凭据。
二.
那种行为只有IE才能帮衬。(别的的浏览器只是会铭记密码,在达成上实在是区别等的。)

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

回到顶部

在IIS中布置Windows身份注解

与使用Forms身份验证的先后不一致,使用Windows身份认证的主次要求额外的安顿步骤。
那么些小节将根本介绍在IIS中配备Windows身份验证,笔者将常用的IIS陆和IIS7.5为例分别介绍那几个安排。

IIS6的配置 请参考下图:

威尼斯人线上娱乐 37

 

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

威尼斯人线上娱乐 38

在意:Windows身份注解是索要设置的,方法请参考下图:

威尼斯人线上娱乐 39

回去顶部

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

在上篇博客中,小编出现说法了什么用代码访问1个应用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 那一个登录名……

转自:

至于浏览器的登录对话框难点

当我们用浏览器访问一个利用Windows身份申明的网址时,浏览器都会弹出一个会话框(左IE,右Safari):

威尼斯人线上娱乐 40

此刻,必要大家输入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汉兰达L 视为 Intranet(本地)。 肆. Internet Explorer
    的 Intranet 区域的安全性设置必须设为“只在 Intranet 区域活动登录”。 5.
    请求Web页的用户必须具备访问该Web页以及该Web页中援引的有着指标的熨帖的文件系统(NTFS)权限。
  2. 用户必须用域帐号登录到Windows 。

在那多少个条件中,假使网址是在3个Windows域中运作,除了第3条或许不满足外,别的条件应该都不难满足(第陆条是私下认可值)。
由此,要让IE不提示输入登录帐号,只要确认保证第二条满足就能够了。
上边包车型大巴图纸演示了怎么样做到这些布局:(注意:配置情势也契合用域名访问的气象)

威尼斯人线上娱乐 41

 

除此以外,除了在IE中安装Intranet外,还足以在做客网址时,用总括机名代替IP地址也许域名
那么IE始终认为是在访问Intranet内的网址,此时也不会弹出登录对话框。

在此,我想再啰嗦3句: 1.
IE在集成Windows身份注脚时,固然不提拔登录对话框,但是不意味着不安全,它会自行传递登录凭据。
二.
那种行为只有IE才能支撑。(别的的浏览器只是会铭记密码,在贯彻上实在是不雷同的。)

  1. 集成Windows身份验证,也只适合在Intranet的环境中央银行使。

回来顶部

在客户端代码中做客Windows身份注脚的页面

在上篇博客中,我出现说法了怎么着用代码访问3个用到Forms身份表明的网址中的受限页面,方法是行使CookieContainer对象收取服务端生的记名Cookie。
但是,在Windows身份认证的网址中,身份验证的长河产生在IIS中,而且平素不应用Cookie保存登录状态,而是供给在伸手时发送须求的身份验证消息。

在应用代码做为客户端访问Web服务器时,大家依旧必要采取HttpWebRequest对象。
为了能让HttpWebRequest在走访IIS时发送要求的身份验证消息,HttpWebRequest提供1个性情都得以成功这么些效应:

// 获取或设置请求的身份验证信息。
//
// 返回结果:
//     包含与该请求关联的身份验证凭据的 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; 此方法在里面会调用后边的格局,由此与眼下的形式是千篇1律的。 叁.
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地图