何以赢安妥前系统用户对文本/文件夹的操作权限?

阅读目录

细说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#文本夹权限操作

  • 开始
  • 认识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那一个接口有着10分关键的功能。
前者定义用户对象的基本功效,后者定义标识对象的基本功效,
区别的地位认证方式取得的那二个接口的实例也是见仁见智的。

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

在Forms身份验证中,我们须要创立登录页面,让用户提交用户名和密码,然后检查用户名和密码的不利,
接下来创设1个包蕴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 Win32 函数(通过 P/Invoke)
来分明是还是不是授权经过身份验证的客户端访问请求的文书。
借使该文件的平安描述符的专擅访问控制列表 (DACL) 中至少含有1个 Read
访问控制项 (ACE),则允许该请求继续。 不然,FileAuthorizationModule
类调用 HttpApplication.CompleteRequest 方法并将状态码 40壹 重返到客户端。

在Windows身份认证中,验证工作至关重如若由IIS达成的,WindowsAuthenticationModule其实只是肩负创立WindowsPrincipal和WindowsIdentity而已。
顺便介绍一下:Windows 身份验证又分为“NTLM 身份验证”和“Kerberos v五身份验证”三种,
关于那三种Windows身份验证的越多表明可查看MSDN技术小说:诠释:ASP.NET
二.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 —
    对文件的造访权限详细音信(读/写等),可知上面列表: 

金沙注册送58 1金沙注册送58 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那三个项目让大家能够方便地从托管代码中访问
Active Directory 域服务。

一经大家要在”test.corp”那么些域中搜索有个别用户音信,大家得以运用下边包车型大巴语句构造二个DirectoryEntry对象:

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

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

金沙注册送58 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() 设置搜索进度中要摸索的习性列表。 3.
调用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());
    }
}

结果如下:

金沙注册送58 4

在前方的代码,笔者在搜索Active
Directory时,只搜索了”name,givenName,samaccountname,mail”那伍个属性。
然则,LDAP还扶助越多的性质,我们能够运用下边包车型地铁代码查看越来越多的用户音信:金沙注册送58 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;
}

那正是说,大家能够动用那样的代码来博取所需的用户新闻:金沙注册送58 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>

程序运营的效应如下:

金沙注册送58 7

别的,还足以从Active
Directory查询三个誉为memberof的性质(它与Windows用户组非亲非故),有时候可以用它有别于用户,设计与权力相关的操作。

在统筹数据持久化的表结构时,由于此时平昔不“用户表”,那么大家能够直接保存用户的登录名。
剩下的开发工作就与Forms身份验证未有太多的分歧了。

回到顶部

认识ASP.NET Windows身份认证

要动用Windows身份验证方式,须求在web.config设置:

<authentication mode="Windows" />

Windows身份验证做为ASP.NET的暗中同意认证方法,与Forms身份认证在众多基础方面是千篇一律的。 上篇博客我说过:自笔者以为ASP.NET的身价认证的最基本部分其实正是HttpContext.User那本本性所指向的对象。 在接下去的1些,笔者将重大分析那些指标在两种身份认证中有何样差距。

在ASP.NET身份验证进程中,IPrincipal和IIdentity那3个接口有着万分重大的作用。
前者定义用户对象的基本功能,后者定义标识对象的基本功能,
分裂的地位验证方法得到的这一个接口的实例也是例外的。

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

判定用户是或不是对路线拥有访问权限,Windows身份注解。在Forms身份认证中,我们须求创设登录页面,让用户提交用户名和密码,然后检查用户名和密码的科学,
接下来创立一个分包FormsAuthenticationTicket对象的登录Cookie供后续请求使用。
FormsAuthenticationModule在ASP.NET管线的AuthenticateRequest事件中,
解析登录Cookie并创造2个暗含FormsIdentity的GenericPrincipal对象,
然后把它赋值给HttpContext.User。

地点2段话回顾了包蕴了三种身份注解格局的做事格局。
我们得以窥见它们存在以下差距:

  1. Forms身份评释必要Cookie表示登录状态,Windows身份验证则借助于IIS
    2.
    Windows身份验证不要求大家规划登录页面,不用编写登录验证逻辑,由此更易于选用。

在授权阶段,UrlAuthorizationModule如故会基于当下用户检查将要访问的财富是不是获得许可。
接下来,FileAuthorizationModule检查 HttpContext.User.Identity 属性中的
IIdentity 对象是或不是是 WindowsIdentity 类的三个实例。 如若 IIdentity
对象不是 WindowsIdentity 类的一个实例,则 FileAuthorizationModule
类甘休处理。 倘使存在 WindowsIdentity 类的3个实例,则
FileAuthorizationModule 类调用 AccessCheck Win32 函数(通过 P/Invoke)
来鲜明是还是不是授权经过身份验证的客户端访问请求的文件。
假如该公文的安全描述符的妄动访问控制列表 (DACL) 中至少含有1个 Read
访问控制项 (ACE),则允许该请求继续。 否则,FileAuthorizationModule
类调用 HttpApplication.CompleteRequest 方法并将意况码 40一 重返到客户端。

在Windows身份认证中,验证工作关键是由IIS完结的,WindowsAuthenticationModule其实只是负责创设WindowsPrincipal和WindowsIdentity而已。
顺便介绍一下:Windows 身份验证又分为“NTLM 身份验证”和“Kerberos v伍身份验证”二种,
关于那三种Windows身份表明的越来越多说明可查阅MSDN技术小说:诠释:ASP.NET
二.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);
    }
}

程序运维的功效如下:

金沙注册送58 8

回来顶部

访问 Active Directory

我们普通使用LDAP协议来访问Active Directory, 在.net
framework中提供了DirectoryEntry和DirectorySearcher这1个连串让我们能够1本万利地从托管代码中做客
Active Directory 域服务。

只要我们要在”test.corp”那个域中搜索某些用户消息,大家得以使用上面包车型地铁语句构造二个DirectoryEntry对象:

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

在那段代码中,作者动用硬编码的措施把域名写进了代码。
小编们怎样精通当前总结机所使用的是哪个域名呢?
金沙注册送58,答案是:查看“小编的微处理器”的属性对话框:

金沙注册送58 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格式筛选器,那是多个字符串。
  2. 往往调用PropertiesToLoad.Add() 设置搜索进度中要寻找的质量列表。
  3. 调用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());
    }
}

结果如下:

金沙注册送58 10

在前头的代码,作者在搜索Active
Directory时,只搜索了”name,givenName,samaccountname,mail”这四特特性。
可是,LDAP还帮忙越来越多的属性,我们能够动用上边包车型客车代码查看更加多的用户消息: 金沙注册送58 11

回来顶部

认识ASP.NET Windows身份认证

要利用Windows身份验证形式,必要在web.config设置:

<authentication mode="Windows" />

Windows身份验证做为ASP.NET的暗中认可认证格局,与Forms身份认证在许多基础方面是同等的。
上篇博客我说过:自个儿觉得ASP.NET的身份认证的最基本部分其实正是HttpContext.User这一个特性所针对的指标。
在接下去的片段,我将器重分析那些指标在两种身份认证中有啥分裂。

在ASP.NET身份验证进度中,IPrincipal和IIdentity这3个接口有着丰盛关键的效应。
前者定义用户对象的基本功用,后者定义标识对象的基本效率,
不相同的地点验证情势取得的那贰个接口的实例也是例外的。

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并创办3个饱含FormsIdentity的GenericPrincipal对象,
然后把它赋值给HttpContext.User。

上边2段话回顾了归纳了三种身份认证方法的工作格局。
大家能够窥见它们存在以下差异: 一.
Forms身份认证须求Cookie表示登录情况,Windows身份注脚则依靠于IIS 贰.
Windows身份评释不要求我们统一筹划登录页面,不用编写登录验证逻辑,因而更便于采纳。

在授权阶段,UrlAuthorizationModule依然会基于当下用户检查将要访问的财富是或不是获得许可。
接下来,FileAuthorizationModule检查 HttpContext.User.Identity 属性中的
IIdentity 对象是还是不是是 WindowsIdentity 类的三个实例。 假诺 IIdentity
对象不是 WindowsIdentity 类的贰个实例,则 FileAuthorizationModule
类停止处理。 假如存在 WindowsIdentity 类的贰个实例,则
FileAuthorizationModule 类调用 AccessCheck Win3二 函数(通过 P/Invoke)
来显著是或不是授权经过身份验证的客户端访问请求的文本。
要是该公文的安全描述符的随机访问控制列表 (DACL) 中至少含有几个 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这2个与用户地方相关的靶子。

回去顶部

安全上下文与用户模拟

在ASP.NET
Windows身份认证环境中,与用户相关的攀枝花上下文对象保存在HttpContext.User属性中,是1个门类为WindowsPrincipal的指标,
我们还足以访问HttpContext.User.Identity来收获经过身份认证的用户标识,它是1个WindowsIdentity类型的对象。

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

金沙注册送58 12

当今涂改一下web.config中设置:(只顾:后边加了一句配置

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

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

金沙注册送58 13

证实: 一. FISH-S安德拉V200三是自作者的持筹握算机名。它在一个未有域的环境中。 二.
fish-li是自个儿的一个Windows帐号的登录名。 3.
网址布置在IIS陆中,进度以NETWO凯雷德K SERAV4VICE帐号运行。 四.
开辟网页时,笔者输入的用户名是fish-li

前边二张图纸的异样之处其实也正是ASP.NET的“模拟”所宣布的功效。

至于模拟,小编想说4点: 1.
在ASP.NET中,大家理应访问HttpContext.User.Identity获取当前用户标识,那么就不存在难题(那儿能够不须要效法),例如FileAuthorizationModule正是如此处理的。
2.
模拟只是在ASP.NET应用程序访问Windows系统资源时索要运用Windows的平安全检查查效能才会有用。

  1. Forms身份验证也能计划模拟功用,但只好模拟一个Windows帐户。 四.
    大多数动静下是不必要效法的。

回去顶部

在ASP.NET中访问Active Directory

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

那么,大家能够动用那样的代码来赢得所需的用户音讯: 金沙注册送58 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>

程序运营的功用如下:

金沙注册送58 15

除此以外,还足以从Active
Directory查询三个叫做memberof的属性(它与Windows用户组非亲非故),有时候能够用它有别于用户,设计与权力相关的操作。

在规划数据持久化的表结构时,由于在此以前卫无“用户表”,那么我们能够直接保存用户的登录名。
剩下的开支工作就与Forms身份申明未有太多的差距了。

回来顶部

访问 Active Directory

咱俩常见采纳LDAP协议来访问Active Directory, 在.net
framework中提供了DirectoryEntry和DirectorySearcher这个种类让我们得以便宜地从托管代码中做客
Active Directory 域服务。

比方大家要在”test.corp”这几个域中搜索有些用户新闻,我们得以选用上边包车型大巴语句构造一个DirectoryEntry对象:

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

在那段代码中,作者使用硬编码的点子把域名写进了代码。
我们怎么精通当前电脑所选用的是哪些域名呢?
答案是:查看“小编的电脑”的习性对话框:

金沙注册送58 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格式筛选器,那是一个字符串。 二.
屡屡调用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());
    }
}

结果如下:

金沙注册送58 17

在前方的代码,小编在搜索Active
Directory时,只搜索了”name,givenName,samaccountname,mail”那陆个属性。
可是,LDAP还支持越来越多的品质,我们可以使用上面包车型地铁代码查看更加多的用户消息:
金沙注册送58 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的配置 请参考下图:

金沙注册送58 19

 

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

金沙注册送58 20

留神:Windows身份认证是内需设置的,方法请参考下图:

金沙注册送58 21

回来顶部

使用Active Directory验证用户地方

后边介绍了ASP.NET
Windows身份认证,在这种艺术下,IIS和WindowsAuthenticationModule为大家贯彻了用户地点验证的进度。
然则,有时也许是因为种种原因,必要大家以编制程序的诀窍利用Active
Directory验证用户身份,比如:在WinForm主次,也许其余的验证逻辑。

作者们不光能够从Active
Directory中查询用户音讯,也可以用它来落到实处认证用户地点,那样便得以达成和谐的记名验证逻辑。

不管是如何行使Active
Directory,我们都亟需运用DirectoryEntry和DirectorySearcher那2个指标。
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);
    }
}

程序运营的机能如下:

金沙注册送58 22

归来顶部

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

那便是说,大家能够使用那样的代码来收获所需的用户信息:
金沙注册送58 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>

程序运转的作用如下:

金沙注册送58 24

其余,还足以从Active
Directory查询一个名字为memberof的习性(它与Windows用户组毫不相关),有时候能够用它有别于用户,设计与权力相关的操作。

在设计数据持久化的表结构时,由于此时从未有过“用户表”,那么大家可以直接保存用户的登录名。
剩下的开发工作就与Forms身份验证未有太多的分歧了。

重返顶部

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

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

金沙注册送58 25

此刻,必要我们输入Windows的记名帐号,然后提交IIS验证身份。

第一回弹出这些对话框很正规:因为程序要表达用户的地位。
可是,每一回关闭浏览器下次再次打开页面时,又会产出此对话框,此时倍感就很不方便人民群众了。
纵然有点浏览器能记住用户名和密码,但本人发觉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 。

在这一个条件中,假诺网址是在二个Windows域中运作,除了第一条大概不满意外,其它条件应该都简单满足(第陆条是暗中同意值)。
因而,要让IE不提醒输入登录帐号,只要确认保证第3条知足就能够了。
上面包车型大巴图形演示了如何成功那几个布局:(注意:配置形式也契合用域名访问的气象)

金沙注册送58 26

 

除此以外,除了在IE中安装Intranet外,仍是能够在走访网址时,用微型总括机名代替IP地址只怕域名
那么IE始终认为是在走访Intranet内的网址,此时也不会弹出登录对话框。

在此,笔者想再啰嗦三句: 1.
IE在集成Windows身份认证时,固然不提拔登录对话框,不过不意味不安全,它会活动传送登录凭据。
2.
那种作为唯有IE才能支持。(别的的浏览器只是会铭记密码,在落到实处上其实是不平等的。)

  1. 集成Windows身份注明,也只适合在Intranet的条件中应用。

归来顶部

安然上下文与用户模拟

在ASP.NET
Windows身份认证环境中,与用户相关的安全上下文对象保存在HttpContext.User属性中,是一个类型为WindowsPrincipal的指标,
我们还足以访问HttpContext.User.Identity来获取经过身份认证的用户标识,它是八个WindowsIdentity类型的对象。

在.NET
Framework中,大家得以因此WindowsIdentity.GetCurrent()获取与如今线程相关的WindowsIdentity对象,
那种艺术取得的是现阶段运作的Win32线程的贺州上下文标识。
由于ASP.NET运转在IIS进度中,因而ASP.NET线程的平安标识其实是从IIS的进度中一连的,
所以此时用三种方法取得的WindowsIdentity对象实际是不一样的。

在Windows操作系统中,许多权力检查都是依据Win32线程的安全上下文标识,
于是前方所说的三种WindowsIdentity对象会导致编制程序模型的不雷同难点,
为了缓解这一个题材,ASP.NET提供了“模拟”功效,同意线程以一定的Windows帐户的平安上下文来访问财富。

为了能越来越好的领悟模拟的功用,笔者准备了二个示范(ShowWindowsIdentity.ashx):

public class ShowWindowsIdentity : IHttpHandler {

    public void ProcessRequest (HttpContext context) {
        // 要观察【模拟】的影响,
        // 可以启用,禁止web.config中的设置:<identity impersonate="true"/>

        context.Response.ContentType = "text/plain";

        context.Response.Write(Environment.UserDomainName + "\\" + Environment.UserName + "\r\n");

        WindowsPrincipal winPrincipal = (WindowsPrincipal)HttpContext.Current.User;
        context.Response.Write(string.Format("HttpContext.Current.User.Identity: {0}, {1}\r\n", 
                winPrincipal.Identity.AuthenticationType, winPrincipal.Identity.Name));

        WindowsPrincipal winPrincipal2 = (WindowsPrincipal)Thread.CurrentPrincipal;
        context.Response.Write(string.Format("Thread.CurrentPrincipal.Identity: {0}, {1}\r\n",
                winPrincipal2.Identity.AuthenticationType, winPrincipal2.Identity.Name));

        WindowsIdentity winId = WindowsIdentity.GetCurrent();
        context.Response.Write(string.Format("WindowsIdentity.GetCurrent(): {0}, {1}",
                winId.AuthenticationType, winId.Name));
    }

首先,在web.config中设置:

<authentication mode="Windows" />

留神:要把网址安顿在IIS中,不然看不出效果。

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

金沙注册送58 27

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

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

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

金沙注册送58 28

说明:

  1. FISH-SLacrosseV200三是本人的预计机名。它在二个没有域的条件中。
  2. fish-li是小编的2个Windows帐号的登录名。
  3. 网址安顿在IIS六中,进度以NETWOTiguanK SETiguanVICE帐号运营。
  4. 开拓网页时,小编输入的用户名是fish-li

眼下贰张图片的出入之处其实约等于ASP.NET的“模拟”所抒发的功效。

至于模拟,小编想说4点:
1.
在ASP.NET中,大家理应访问HttpContext.User.Identity获取当前用户标识,那么就不存在问题(那时能够不必要效法),例如FileAuthorizationModule正是这么处理的。
2.
仿照只是在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还提供2个构造函数可让大家输入用户名和密码:

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

程序运维的坚守如下:

金沙注册送58 29

回去顶部

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

在上篇博客中,作者现身说法了什么用代码访问贰个运用Forms身份认证的网址中的受限页面,方法是行使CookieContainer对象吸收服务端生的记名Cookie。
不过,在Windows身份验证的网址中,身份验证的长河爆发在IIS中,而且向来不使用Cookie保存登录情形,而是须求在呼吁时发送要求的身份验证音讯。

在运用代码做为客户端访问Web服务器时,大家如故要求利用HttpWebRequest对象。
为了能让HttpWebRequest在走访IIS时发送须求的身份验证消息,HttpWebRequest提供三个属性都能够做到那些效果:

// 获取或设置请求的身份验证信息。
//
// 返回结果:
//     包含与该请求关联的身份验证凭据的 System.Net.ICredentials。默认为 null。
public override ICredentials Credentials { get; set; }


// 获取或设置一个 System.Boolean 值,该值控制默认凭据是否随请求一起发送。
//
// 返回结果:
//     如果使用默认凭据,则为 true;否则为 false。默认值为 false。
public override bool UseDefaultCredentials { get; set; }

下边是自己准备的一体化的演示代码(注意代码中的注释)

static void Main(string[] args)
{
    try {
        // 请把WindowsAuthWebSite1这个网站部署在IIS中,
        // 开启Windows认证方式,并禁止匿名用户访问。
        // 然后修改下面的访问地址。
        HttpWebRequest request = 
            (HttpWebRequest)WebRequest.Create("http://localhost:33445/Default.aspx");

        // 下面三行代码,启用任意一行都是可以的。
        request.UseDefaultCredentials = true;
        //request.Credentials = CredentialCache.DefaultCredentials;
        //request.Credentials = CredentialCache.DefaultNetworkCredentials;
        // 如果上面的三行代码全被注释了,那么将会看到401的异常信息。

        using( HttpWebResponse response = (HttpWebResponse)request.GetResponse() ) {
            using( StreamReader sr = new StreamReader(response.GetResponseStream()) ) {
                Console.WriteLine(sr.ReadToEnd());
            }
        }
    }
    catch( WebException wex ) {
        Console.WriteLine("=====================================");
        Console.WriteLine("异常发生了。");
        Console.WriteLine("=====================================");
        Console.WriteLine(wex.Message);
    }
}

实则根本部分依然安装UseDefaultCredentials或然Credentials,代码中的三种格局是立竿见影的。
那二种方法的异样: 1. Credentials = CredentialCache.DefaultCredentials;
表示在出殡和埋葬请求会带受骗前用户的身份验证凭据。 2. UseDefaultCredentials =
true; 此方法在里边会调用前面包车型地铁方法,由此与前方的法子是平等的。 3.
Credentials = CredentialCache.DefaultNetworkCredentials; 是在.NET
二.0中引用的新点子。

关于DefaultCredentials和DefaultNetworkCredentials的越来越多差距,请看自个儿收10的报表:

Credentials属性

发明类型

实例类型

.NET援助版本

DefaultCredentials

ICredentials

SystemNetworkCredential

从1.0开始

DefaultNetworkCredentials

NetworkCredential

SystemNetworkCredential

从2.0开始

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

 

在竣事那篇博客以前,作者想自个儿应该谢谢新蛋。
在新蛋的网络环境中,让作者学会了动用Windows身份验证。
除了谢谢之外,作者明日还特别挂念 fl四伍 那些登录名……

在IIS中布局Windows身份注解

与行使Forms身份证明的次第不一致,使用Windows身份验证的次第要求额外的布置步骤。
这几个小节将第2介绍在IIS中配置Windows身份表明,笔者将常用的IIS陆和IIS7.5为例分别介绍这一个布署。

IIS6的配置 请参考下图:

金沙注册送58 30

 

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

金沙注册送58 31

只顾:Windows身份认证是必要设置的,方法请参见下图:

金沙注册送58 32

回去顶部

日喀则上下文与用户模拟

在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操作系统中,许多权力检查都以依据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,将见到如下图所示的结果:

金沙注册送58 33

今昔修改一下web.config中安装:(瞩目:前边加了一句配置

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

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

金沙注册送58 34

证实: 一. FISH-S奥迪Q5V200三是本身的计算机名。它在2个未有域的条件中。 二.
fish-li是本人的1个Windows帐号的登录名。 三.
网址陈设在IIS六中,进程以NETWO奥迪Q5K SEHighlanderVICE帐号运转。 肆.
开辟网页时,作者输入的用户名是fish-li

眼下2张图片的差异之处其实也等于ASP.NET的“模拟”所发挥的功能。

关于模拟,笔者想说4点: 一.
在ASP.NET中,大家理应访问HttpContext.User.Identity获取当前用户标识,那么就不设非常(那时候得以不供给效法),例如FileAuthorizationModule就是那般处理的。
二.
仿照只是在ASP.NET应用程序访问Windows系统能源时要求使用Windows的平安全检查查职能才会有用。

  1. Forms身份验证也能配置模拟成效,但不得不模拟一个Windows帐户。 4.
    多数状态下是不要求效法的。

回去顶部

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

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

金沙注册送58 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 必须把所请求的 U悍马H2L 视为 Intranet(本地)。
  4. Internet Explorer 的 Intranet 区域的安全性设置必须设为“只在 Intranet
    区域活动登录”。
    伍.
    请求Web页的用户必须拥有访问该Web页以及该Web页中援引的保有目的的贴切的文件系统(NTFS)权限。
  5. 用户必须用域帐号登录到Windows 。

在那多少个规范中,如若网址是在3个Windows域中运转,除了第三条或者不满意外,别的条件应该都不难满意(第陆条是默许值)。
因而,要让IE不提醒输入登录帐号,只要确认保障第二条满意就足以了。
上边包车型客车图样演示了什么样形成那个布局:(注意:配置方式也符合用域名访问的动静)

金沙注册送58 36

 

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

在此,小编想再啰嗦3句:
一.
IE在集成Windows身份认证时,就算不晋升登录对话框,不过不代表不安全,它会活动传递登录凭据。
二.
那种作为唯有IE才能支撑。(别的的浏览器只是会记住密码,在达成上实际是分裂等的。)

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

回去顶部

在IIS中安顿Windows身份注明

与运用Forms身份注解的先后分化,使用Windows身份验证的先后要求额外的陈设步骤。
这些小节将重点介绍在IIS中布置Windows身份申明,作者将常用的IIS陆和IIS七.5为例分别介绍那么些安插。

IIS6的配置 请参考下图:

金沙注册送58 37

 

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

金沙注册送58 38

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

金沙注册送58 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
    二.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):

金沙注册送58 40

那时候,要求大家输入Windows的记名帐号,然后提交IIS验证身份。

第三次弹出这些对话框很正规:因为程序要表达用户的身份。
不过,每一回关闭浏览器下次再次打开页面时,又会出现此对话框,此时感觉就很不便宜了。
就算有点浏览器能记住用户名和密码,但自作者发现FireFox,Opera,Chrome依然会弹出那么些对话框,等待大家点击分明,
只有Safari才不会侵扰用户向来打开网页。
IE的百般“记住自身的密码”复选框完全是个摆放,它根本不会铭记密码!

据此,笔者所试过的享有浏览器中,唯有Safari是最人性化的。
即便在私下认可意况下,即便IE不会记住密码,每便都亟待重新输入。
然而,IE却得以辅助不提示用户输入登录帐号而直白打开网页,
此时IE将应用用户的当前Windows登录帐号传递给IIS验证身份。

要让IE打开3个Windows身份认证的网址不提醒登录对话框,必须知足以下原则:

  1. 非得在 IIS 的 Web 站点属性中启用 Windows 集成身份验证。 二.
    客户端和Web服务器都不可能不在依照Microsoft Windows的同叁个域内。 3. Internet
    Explorer 必须把所请求的 UOdysseyL 视为 Intranet(当地)。 四. Internet Explorer
    的 Intranet 区域的安全性设置必须设为“只在 Intranet 区域活动登录”。 伍.
    请求Web页的用户必须拥有访问该Web页以及该Web页中引用的持有目的的恰到好处的文件系统(NTFS)权限。
  2. 用户必须用域帐号登录到Windows 。

在那多少个规格中,假使网址是在1个Windows域中运作,除了第三条恐怕不满足外,其余条件应该都简单满足(第四条是暗中认可值)。
由此,要让IE不提醒输入登录帐号,只要确认保障第二条知足就能够了。
上面包车型客车图形演示了怎么着成功那一个布局:(注意:配置格局也适合用域名访问的情况)

金沙注册送58 41

 

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

在此,作者想再啰嗦3句: 一.
IE在集成Windows身份注解时,就算不升迁登录对话框,不过不意味不安全,它会自行传送登录凭据。
二.
那种表现唯有IE才能援助。(别的的浏览器只是会铭记密码,在落到实处上实在是不平等的。)

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

回去顶部

在客户端代码中做客Windows身份表明的页面

在上篇博客中,我出现说法了怎么着用代码访问贰个利用Forms身份申明的网址中的受限页面,方法是应用库克ieContainer对象吸收服务端生的记名Cookie。
但是,在Windows身份认证的网址中,身份验证的长河爆发在IIS中,而且根本不选择库克ie保存登录情形,而是须求在呼吁时发送要求的身份验证音讯。

在行使代码做为客户端访问Web服务器时,大家照例需求动用HttpWebRequest对象。
为了能让HttpWebRequest在走访IIS时发送供给的身份验证音信,HttpWebRequest提供3个本性都得以成功这些功用:

// 获取或设置请求的身份验证信息。
//
// 返回结果:
//     包含与该请求关联的身份验证凭据的 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开始

多少个品种的延续关系: 1. NetworkCredential完成了ICredentials接口, 二.
SystemNetworkCredential继承自NetworkCredential。

 

在得了那篇博客从前,小编想本人应该多谢新蛋。
在新蛋的互连网环境中,让自家学会了利用Windows身份认证。
除了感激之外,小编明日还专门挂念 fl四伍 那个登录名……

 

点击那里下载示例代码

相关文章

网站地图xml地图