Windows身份申明,判断用户是否对路线拥有访问权限

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

细说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身份验证。

 1.取得安全音讯DirectorySecurity

DirectorySecurity fileAcl = Directory.GetAccessControl(folder);

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

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

对文本/文件夹权限的详尽操作,可参考一篇博客C#文件夹权限操作

认识ASP.NET Windows身份评释

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

<authentication mode="Windows" />

Windows身份评释做为ASP.NET的暗中同意认证形式,与Forms身份验证在重重基础方面是同一的。Windows身份申明,判断用户是否对路线拥有访问权限。上篇博客我说过:本人觉得ASP.NET的身份验证的最核心部分其实正是HttpContext.User那性情情所针对的对象。在接下去的部分,我将首要分析那些目的在三种身份认证中有哪些差距。

在ASP.NET身份表明进程中,IPrincipal和IIdentity那一个接口有着不行主要的成效。
前者定义用户对象的基本功用,后者定义标识对象的基本作用,
分化的身价验证方法得到的那2个接口的实例也是分裂的。

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

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

下边二段话归纳了回顾了二种身份评释格局的办事办法。
大家能够发现它们存在以下差异: 1.
Forms身份认证必要Cookie表示登录情况,Windows身份注脚则依靠于IIS 2.
Windows身份验证不供给大家规划登录页面,不用编写登录验证逻辑,因而更便于接纳。

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

在Windows身份注明中,验证工作第3是由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这贰个与用户地方相关的靶子。

归来顶部

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

Forms身份注解固然采纳大规模,可是,假诺是在 Windows Active Directory
的环境中使用ASP.NET, 那么使用Windows身份表明也会相比较有利。
方便性表现为:我们毫不再规划登录页面,不用编写登录验证逻辑。而且动用Windows身份认证会有更好的安全保持。

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

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

GetAccessRules()方法重返的是AuthorizationRule集合,此处只必要得到文件权限。

FileSystemAccessRule.aspx)继承自AuthorizationRule,并新增俩个属性

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

澳门葡京备用网址 1澳门葡京备用网址 2

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

View Code

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

故而,如通过当前系统用户名与IdentityReference匹配,即可获得FileSystemAccessRule权限。怎么着获得用户名,见下一段落

访问 Active Directory

咱们常见选用LDAP协议来访问Active Directory, 在.net
framework中提供了DirectoryEntry和DirectorySearcher这么些类型让大家得以便宜地从托管代码中做客
Active Directory 域服务。

假设大家要在”test.corp”那些域中搜索有个别用户消息,我们得以应用上边包车型客车语句构造1个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的摸索。 大家能够利用上面包车型地铁步子来进行搜索: 1. 安装
DirectorySearcher.Filter 提示LDAP格式筛选器,那是二个字符串。 2.
反复调用PropertiesToLoad.Add() 设置搜索进程中要物色的属性列表。 3.
调用FindOne() 方法获得搜索结果。

下边的代码演示了怎么样从Active Directory中寻找登录名为“fl45”的用户新闻:

static void Main(string[] args)
{
    Console.WriteLine(Environment.UserDomainName);
    Console.WriteLine(Environment.UserName);
    Console.WriteLine("------------------------------------------------");

    ShowUserInfo("fl45", GetDomainName());
}

private static string AllProperties = "name,givenName,samaccountname,mail";

public static void ShowUserInfo(string loginName, string domainName)
{
    if( string.IsNullOrEmpty(loginName) || string.IsNullOrEmpty(domainName) )
        return;

    string[] properties = AllProperties.Split(new char[] { '\r', '\n', ',' }, 
                        StringSplitOptions.RemoveEmptyEntries);

    try {
        DirectoryEntry entry = new DirectoryEntry("LDAP://" + domainName);
        DirectorySearcher search = new DirectorySearcher(entry);
        search.Filter = "(samaccountname=" + loginName + ")";

        foreach( string p in properties )
            search.PropertiesToLoad.Add(p);

        SearchResult result = search.FindOne();

        if( result != null ) {
            foreach( string p in properties ) {
                ResultPropertyValueCollection collection = result.Properties[p];
                for( int i = 0; i < collection.Count; i++ )
                    Console.WriteLine(p + ": " + collection[i]);
            }
        }
    }
    catch( Exception ex ) {
        Console.WriteLine(ex.ToString());
    }
}

结果如下:

澳门葡京备用网址 4

在眼下的代码,小编在搜索Active
Directory时,只搜索了”name,givenName,samaccountname,mail”那4天性子。
不过,LDAP还帮忙越来越多的质量,我们得以行使下面的代码查看更加多的用户消息:澳门葡京备用网址 5😉

        private static string AllProperties = @"
homemdb
distinguishedname
countrycode
cn
lastlogoff
mailnickname
dscorepropagationdata
msexchhomeservername
msexchmailboxsecuritydescriptor
msexchalobjectversion
usncreated
objectguid
whenchanged
memberof
msexchuseraccountcontrol
accountexpires
displayname
primarygroupid
badpwdcount
objectclass
instancetype
objectcategory
samaccounttype
whencreated
lastlogon
useraccountcontrol
physicaldeliveryofficename
samaccountname
usercertificate
givenname
mail
userparameters
adspath
homemta
msexchmailboxguid
pwdlastset
logoncount
codepage
name
usnchanged
legacyexchangedn
proxyaddresses
department
userprincipalname
badpasswordtime
objectsid
sn
mdbusedefaults
telephonenumber
showinaddressbook
msexchpoliciesincluded
textencodedoraddress
lastlogontimestamp
company
";

回去顶部

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

归来顶部

3. 获得当前系统用户名/用户组

经过 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     }

 

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

那么,大家能够选拔那样的代码来取得所需的用户消息:澳门葡京备用网址 6😉

public static class UserHelper
{
    /// <summary>
    /// 活动目录中的搜索路径,也可根据实际情况来修改这个值。
    /// </summary>
    public static string DirectoryPath = "LDAP://" + GetDomainName();


    /// <summary>
    /// 获取与指定HttpContext相关的用户信息
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public static UserInfo GetCurrentUserInfo(HttpContext context)
    {
        string loginName = GetUserLoginName(context);
        if( string.IsNullOrEmpty(loginName) )
            return null;

        return GetUserInfoByLoginName(loginName);
    }

    /// <summary>
    /// 根据指定的HttpContext对象,获取登录名。
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public static string GetUserLoginName(HttpContext context)
    {
        if( context == null )
            return null;

        if( context.Request.IsAuthenticated == false )
            return null;

        string userName = context.User.Identity.Name;
        // 此时userName的格式为:UserDomainName\LoginName
        // 我们只需要后面的LoginName就可以了。

        string[] array = userName.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
        if( array.Length == 2 )
            return array[1];

        return null;
    }


    /// <summary>
    /// 根据登录名查询活动目录,获取用户信息。
    /// </summary>
    /// <param name="loginName"></param>
    /// <returns></returns>
    public static UserInfo GetUserInfoByLoginName(string loginName)
    {
        if( string.IsNullOrEmpty(loginName) )
            return null;

        // 下面的代码将根据登录名查询用户在AD中的信息。
        // 为了提高性能,可以在此处增加一个缓存容器(Dictionary or Hashtable)。

        try {
            DirectoryEntry entry = new DirectoryEntry(DirectoryPath);
            DirectorySearcher search = new DirectorySearcher(entry);
            search.Filter = "(SAMAccountName=" + loginName + ")";

            search.PropertiesToLoad.Add("givenName");
            search.PropertiesToLoad.Add("cn");
            search.PropertiesToLoad.Add("mail");
            // 如果还需要从AD中获取其它的用户信息,请参考ActiveDirectoryDEMO

            SearchResult result = search.FindOne();

            if( result != null ) {
                UserInfo info = new UserInfo();
                info.GivenName = result.Properties["givenName"][0].ToString();
                info.FullName = result.Properties["cn"][0].ToString();
                info.Email = result.Properties["mail"][0].ToString();
                return info;
            }
        }
        catch {
            // 如果需要记录异常,请在此处添加代码。
        }
        return null;
    }


    private static string GetDomainName()
    {
        // 注意:这段代码需要在Windows XP及较新版本的操作系统中才能正常运行。
        SelectQuery query = new SelectQuery("Win32_ComputerSystem");
        using( ManagementObjectSearcher searcher = new ManagementObjectSearcher(query) ) {
            foreach( ManagementObject mo in searcher.Get() ) {
                if( (bool)mo["partofdomain"] )
                    return mo["domain"].ToString();
            }
        }
        return null;
    }

}

利用UserHelper的页面代码:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>WindowsAuthentication DEMO  - http://www.cnblogs.com/fish-li/</title>
</head>
<body>
<% if( Request.IsAuthenticated ) { %>
    当前登录全名:<%= Context.User.Identity.Name.HtmlEncode()%> <br />

    <% var user = UserHelper.GetCurrentUserInfo(Context); %>
    <% if( user != null ) { %>
        用户短名:<%= user.GivenName.HtmlEncode()%> <br />
        用户全名:<%= user.FullName.HtmlEncode() %> <br />
        邮箱地址:<%= user.Email.HtmlEncode() %>
    <% } %>    
<% } else { %>
    当前用户还未登录。
<% } %>
</body>
</html>

程序运营的效劳如下:

澳门葡京备用网址 7

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

在筹划数据持久化的表结构时,由于此时不曾“用户表”,那么咱们得以平素保存用户的登录名。
剩下的支付工作就与Forms身份验证没有太多的分裂了。

回来顶部

Forms身份验证固然应用大规模,但是,借使是在 Windows Active Directory
的环境中动用ASP.NET, 那么使用Windows身份注解也会相比较便于。
方便性表现为:我们不要再规划登录页面,不用编写登录验证逻辑。而且动用Windows身份评释会有更好的安全保持。

认识ASP.NET Windows身份验证

要使用Windows身份评释方式,须要在web.config设置:

<authentication mode="Windows" />

Windows身份表明做为ASP.NET的暗许认证情势,与Forms身份验证在重重基础方面是一致的。 上篇博客我说过:自家以为ASP.NET的地点申明的最核心部分其实正是HttpContext.User这几个天性所指向的靶子。 在接下去的一对,作者将注重分析这些指标在三种身份声明中有哪些差异。

在ASP.NET身份注解进度中,IPrincipal和IIdentity那么些接口有着至极主要的功用。
前者定义用户对象的基本作用,后者定义标识对象的基本作用,
区别的身价认证方法赢得的那二个接口的实例也是差别的。

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

在Forms身份验证中,大家要求创建登录页面,让用户提交用户名和密码,然后检查用户名和密码的没错,
接下来成立3个饱含FormsAuthenticationTicket对象的登录Cookie供后续请求使用。
FormsAuthenticationModule在ASP.NET管线的AuthenticateRequest事件中,
解析登录Cookie并创制贰个富含FormsIdentity的GenericPrincipal对象,
然后把它赋值给HttpContext.User。

地点二段话总结了包罗了三种身份验证方法的劳作方法。
大家能够窥见它们存在以下差异:

  1. Forms身份验证要求Cookie表示登录意况,Windows身份认证则凭借于IIS
    2.
    Windows身份认证不必要大家计划登录页面,不用编写登录验证逻辑,由此更便于接纳。

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

在Windows身份验证中,验证工作重大是由IIS达成的,WindowsAuthenticationModule其实只是负担创制WindowsPrincipal和WindowsIdentity而已。
顺便介绍一下:Windows 身份验证又分为“NTLM 身份验证”和“Kerberos v5
身份验证”二种,
关于那三种Windows身份认证的更多表达可查阅MSDN技术小说:诠释:ASP.NET
2.0 中的 Windows
身份验证。
以作者之见,IIS最后采纳哪个种类Windows身份注明格局并不影响大家的花费进程,由此本文不会谈论这些话题。

依照本人的骨子里经历来看,使用Windows身份认证时,首要的开支工作将是依照登录名从Active
Directory获取用户新闻。
因为,此时不须求大家再规划登录进程,IIS与ASP.NET已经为大家准备好了WindowsPrincipal和WindowsIdentity那么些与用户身份相关的指标。

回到顶部

应用Active Directory验证用户身份

前方介绍了ASP.NET
Windows身份认证,在那种办法下,IIS和WindowsAuthenticationModule为我们落实了用户地方验证的历程。
但是,有时大概鉴于各个缘由,必要我们以编制程序的主意接纳Active
Directory验证用户地点,比如:在WinForm主次,只怕其余的印证逻辑。

咱俩不但能够从Active
Directory中查询用户消息,也得以用它来贯彻认证用户地方,那样便足以兑现本身的报到验证逻辑。

不论是是哪些行使Active
Directory,大家都要求选用DirectoryEntry和DirectorySearcher那些指标。DirectoryEntry还提供1个构造函数可让大家输入用户名和密码:

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

要促成协调的登录检查,就必要采取那一个构造函数。
以下是小编写用WinForm写的一个签到检查的示范:

private void btnLogin_Click(object sender, EventArgs e)
{
    if( txtUsername.Text.Length == 0 || txtPassword.Text.Length == 0 ) {
        MessageBox.Show("用户名或者密码不能为空。", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
        return;
    }

    string ldapPath = "LDAP://" + GetDomainName();
    string domainAndUsername = Environment.UserDomainName + "\\" + txtUsername.Text;
    DirectoryEntry entry = new DirectoryEntry(ldapPath, domainAndUsername, txtPassword.Text);

    DirectorySearcher search = new DirectorySearcher(entry);

    try {
        SearchResult result = search.FindOne();

        MessageBox.Show("登录成功。", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    catch( Exception ex ) {
        // 如果用户名或者密码不正确,也会抛出异常。
        MessageBox.Show(ex.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Stop);
    }
}

程序运转的效应如下:

澳门葡京备用网址 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格式筛选器,那是二个字符串。
  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”那5个天性。
可是,LDAP还援助更加多的习性,大家可以动用上边的代码查看越多的用户音讯: 澳门葡京备用网址 11

归来顶部

平安上下文与用户模拟

在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,将看到如下图所示的结果:

澳门葡京备用网址 12

以往修改一下web.config中装置:(在意:前边加了一句配置澳门葡京备用网址 ,)

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

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

澳门葡京备用网址 13

表明: 1. FISH-S酷威V二〇〇〇是自家的测度机名。它在二个没有域的条件中。 2.
fish-li是作者的多个Windows帐号的登录名。 3.
网站安顿在IIS6中,进度以NETWO奥迪Q5K SEXC60VICE帐号运转。 4.
打开网页时,作者输入的用户名是fish-li

前方二张图纸的异样之处其实也正是ASP.NET的“模拟”所发挥的机能。

至于模拟,小编想说四点: 1.
在ASP.NET中,我们相应访问HttpContext.User.Identity获取当前用户标识,那么就不设不正常(那时候能够不须求效法),例如FileAuthorizationModule正是那样处理的。
2.
效仿只是在ASP.NET应用程序访问Windows系统能源时索要接纳Windows的莱芜检查效用才会有用。

  1. Forms身份表明也能配备模拟功效,但不得不模拟一个Windows帐户。 4.
    多数景观下是不要求效法的。

回来顶部

认识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身份注解中,大家须要创建登录页面,让用户提交用户名和密码,然后检查用户名和密码的正确,
接下来创造一个包括FormsAuthenticationTicket对象的报到Cookie供后续请求使用。
FormsAuthenticationModule在ASP.NET管线的AuthenticateRequest事件中,
解析登录Cookie并创立3个含有FormsIdentity的GenericPrincipal对象,
然后把它赋值给HttpContext.User。

地点二段话回顾了总结了二种身份表明格局的办事办法。
大家能够发现它们存在以下差距: 1.
Forms地方认证必要Cookie表示登录情形,Windows身份验证则借助于IIS 2.
Windows身份验证不必要大家布署登录页面,不用编写登录验证逻辑,因而更便于选取。

在授权阶段,UrlAuthorizationModule照旧会依据当前用户检查将要访问的能源是不是得到许可。
接下来,FileAuthorizationModule检查 HttpContext.User.Identity 属性中的
IIdentity 对象是还是不是是 WindowsIdentity 类的1个实例。 假若 IIdentity
对象不是 WindowsIdentity 类的3个实例,则 FileAuthorizationModule
类甘休处理。 要是存在 WindowsIdentity 类的1个实例,则
FileAuthorizationModule 类调用 AccessCheck Win32 函数(通过 P/Invoke)
来明确是还是不是授权经过身份验证的客户端访问请求的文书。
假使该文件的天水描述符的任性访问控制列表 (DACL) 中至少含有叁个 Read
访问控制项 (ACE),则允许该请求继续。 不然,FileAuthorizationModule
类调用 HttpApplication.CompleteRequest 方法并将气象码 401
重回到客户端。 

在Windows身份验证中,验证工作第叁是由IIS实现的,WindowsAuthenticationModule其实只是负责创设WindowsPrincipal和WindowsIdentity而已。
顺便介绍一下:Windows 身份验证又分为“NTLM 身份验证”和“Kerberos v5
身份验证”二种,
关于那三种Windows身份评释的越来越多表明可查阅MSDN技术小说:诠释:ASP.NET
2.0 中的 Windows
身份验证。
在小编眼里,IIS最终采纳哪一种Windows身份认证方法并不影响我们的开发进度,由此本文不会谈论这些话题。

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

回到顶部

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

那就是说,大家得以应用那样的代码来获得所需的用户消息: 澳门葡京备用网址 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身份注明没有太多的差别了。

回到顶部

在IIS中布署Windows身份认证

与使用Forms身份注解的顺序差别,使用Windows身份验证的先后须要格外的布署步骤。
这么些小节将根本介绍在IIS中配备Windows身份注解,笔者将常用的IIS6和IIS7.5为例分别介绍那么些配置。

IIS6的配置 请参考下图:

澳门葡京备用网址 16

 

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

澳门葡京备用网址 17

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

澳门葡京备用网址 18

回到顶部

访问 Active Directory

大家常见选拔LDAP协议来访问Active Directory, 在.net
framework中提供了DirectoryEntry和DirectorySearcher那三个品类让我们能够便宜地从托管代码中做客
Active Directory 域服务。

假设大家要在”test.corp”那几个域中搜索有个别用户消息,大家能够应用上面包车型大巴语句构造2个DirectoryEntry对象:

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

在那段代码中,小编使用硬编码的方法把域名写进了代码。
大家什么样知道当前电脑所采纳的是哪个域名呢?
答案是:查看“小编的处理器”的质量对话框:

澳门葡京备用网址 19

留神:那么些域名不自然与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());
    }
}

结果如下:

澳门葡京备用网址 20

在前边的代码,小编在搜索Active
Directory时,只搜索了”name,givenName,samaccountname,mail”那陆个本性。
然则,LDAP还协理越多的属性,我们能够运用上边包车型客车代码查看更多的用户消息:
澳门葡京备用网址 21

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

回来顶部

应用Active Directory验证用户身份

前方介绍了ASP.NET
Windows身份验证,在那种方式下,IIS和WindowsAuthenticationModule为大家落实了用户身份认证的进度。
但是,有时大概鉴于各类缘由,须求大家以编制程序的艺术选拔Active
Directory验证用户地方,比如:在WinForm主次,也许别的的表达逻辑。

咱俩不光能够从Active
Directory中查询用户消息,也可以用它来兑现认证用户地方,那样便得以兑现本身的登录验证逻辑。

无论是是如何利用Active
Directory,大家都亟待运用DirectoryEntry和DirectorySearcher这3个对象。
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);
    }
}

程序运维的功用如下:

澳门葡京备用网址 22

回到顶部

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

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

澳门葡京备用网址 23

此时,供给我们输入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 必须把所请求的 ULANDL 视为 Intranet(本地)。 4. Internet Explorer
    的 Intranet 区域的安全性设置必须设为“只在 Intranet 区域活动登录”。 5.
    请求Web页的用户必须怀有访问该Web页以及该Web页中引用的富有目的的合适的文件系统(NTFS)权限。
  2. 用户必须用域帐号登录到Windows 。

在这多少个标准中,假诺网站是在三个Windows域中运作,除了第③条恐怕不满足外,其余条件应该都简单满足(第伍条是暗中认可值)。
由此,要让IE不提示输入登录帐号,只要确定保障第叁条满意就足以了。
上面包车型地铁图纸演示了什么样达成这几个布局:(注意:配置情势也适合用域名访问的景观)

澳门葡京备用网址 24

 

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

在此,小编想再啰嗦三句: 1.
IE在集成Windows身份验证时,即使不提示登录对话框,不过不表示不安全,它会自动传递登录凭据。
2.
那种作为唯有IE才能支撑。(别的的浏览器只是会记住密码,在落成上其实是不相同等的。)

  1. 集成Windows身份申明,也只适合在Intranet的环境中应用。

回到顶部

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

那么,大家能够选用那样的代码来得到所需的用户新闻:
澳门葡京备用网址 25

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>

程序运维的效益如下:

澳门葡京备用网址 26

除此以外,还能从Active
Directory查询1个称作memberof的性质(它与Windows用户组毫无干系),有时候能够用它有别于用户,设计与权力相关的操作。

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

重返顶部

安全上下文与用户模拟

在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,将见到如下图所示的结果:

澳门葡京备用网址 27

以往涂改一下web.config中安装:(瞩目:前面加了一句配置

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

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

澳门葡京备用网址 28

说明:

  1. FISH-SEscortV2004是自个儿的计量机名。它在1个没有域的环境中。
  2. fish-li是本人的二个Windows帐号的登录名。
  3. 网站安插在IIS6中,进度以NETWO奥德赛K SE奥德赛VICE帐号运转。
  4. 开拓网页时,笔者输入的用户名是fish-li

前方二张图片的歧异之处其实也正是ASP.NET的“模拟”所发挥的效应。

至于模拟,小编想说四点:
1.
在ASP.NET中,大家相应访问HttpContext.User.Identity获取当前用户标识,那么就不存在难点(那时候得以不须要效法),例如FileAuthorizationModule正是这样处理的。
2.
仿照只是在ASP.NET应用程序访问Windows系统财富时需求采纳Windows的安检职能才会有用。

  1. Forms身份评释也能陈设模拟功用,但不得不模拟五个Windows帐户。
  2. 大多数情景下是不须要效法的。

重临顶部

在客户端代码中访问Windows身份注解的页面

在上篇博客中,小编出现说法了如何用代码访问二个行使Forms身份证明的网站中的受限页面,方法是选拔CookieContainer对象吸收服务端生的登录Cookie。
可是,在Windows身份注明的网站中,身份验证的进程发生在IIS中,而且根本不应用Cookie保存登录景况,而是须求在伸手时发送供给的身份验证音讯。

在利用代码做为客户端访问Web服务器时,我们依旧须要动用HttpWebRequest对象。
为了能让HttpWebRequest在造访IIS时发送需求的身份验证音信,HttpWebRequest提供三个天性都可以形成那一个功用:

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


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

上边是自己准备的总体的演示代码(注意代码中的注释)

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

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

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

实在首要部分照旧安装UseDefaultCredentials或许Credentials,代码中的二种格局是立竿见影的。
那二种方法的反差: 1. Credentials = CredentialCache.DefaultCredentials;
表示在发送请求会带上当前用户的身份验证凭据。 2. UseDefaultCredentials =
true; 此方法在中间会调用前面的办法,因而与日前的点子是相同的。 3.
Credentials = CredentialCache.DefaultNetworkCredentials; 是在.NET
2.0中援引的新章程。

关于DefaultCredentials和DefaultNetworkCredentials的更加多差异,请看自个儿收拾的表格:

Credentials属性

发明类型

实例类型

.NET协助版本

DefaultCredentials

ICredentials

SystemNetworkCredential

从1.0开始

DefaultNetworkCredentials

NetworkCredential

SystemNetworkCredential

从2.0开始

四个档次的继续关系: 1. NetworkCredential完成了ICredentials接口, 2.
SystemNetworkCredential继承自NetworkCredential。

 

在收尾那篇博客以前,笔者想自身应该谢谢新蛋。
在新蛋的网络环境中,让作者学会了选择Windows身份注脚。
除了多谢之外,笔者前天还特地纪念 fl45 那个登录名……

运用Active Directory验证用户身份

前方介绍了ASP.NET
Windows身份评释,在那种方法下,IIS和WindowsAuthenticationModule为我们贯彻了用户身份认证的进度。
可是,有时也许由于种种原因,须求大家以编制程序的措施利用Active
Directory验证用户地点,比如:在WinForm先后,恐怕别的的认证逻辑。

大家不光能够从Active
Directory中询问用户音讯,也能够用它来贯彻认证用户地点,那样便足以兑现自个儿的登录验证逻辑。

不论是如何行使Active
Directory,大家都必要动用DirectoryEntry和DirectorySearcher那1个目的。
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);
    }
}

程序运转的法力如下:

澳门葡京备用网址 29

重临顶部

在IIS中计划Windows身份注解

与使用Forms身份注明的顺序不一样,使用Windows身份验证的先后须要额外的安插步骤。
那个小节将根本介绍在IIS中配备Windows身份评释,作者将常用的IIS6和IIS7.5为例分别介绍那么些安排。

IIS6的配置 请参考下图:

澳门葡京备用网址 30

 

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

澳门葡京备用网址 31

注意:Windows身份注明是亟需设置的,方法请参考下图:

澳门葡京备用网址 32

回到顶部

安然上下文与用户模拟

在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,将看到如下图所示的结果:

澳门葡京备用网址 33

今昔修改一下web.config中设置:(专注:前边加了一句配置

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

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

澳门葡京备用网址 34

表达: 1. FISH-SRubiconV2004是自笔者的一个钱打二十七个结机名。它在一个没有域的环境中。 2.
fish-li是自个儿的2个Windows帐号的登录名。 3.
网站陈设在IIS6中,进度以NETWOCR-VK SE奥迪Q3VICE帐号运转。 4.
开拓网页时,小编输入的用户名是fish-li

前方二张图纸的差距之处其实也等于ASP.NET的“模拟”所发挥的功效。

有关模拟,作者想说四点: 1.
在ASP.NET中,大家应有访问HttpContext.User.Identity获取当前用户标识,那么就不设有毛病(那儿能够不需求效法),例如FileAuthorizationModule正是这么处理的。
2.
效仿只是在ASP.NET应用程序访问Windows系统能源时须要动用Windows的长治检查职能才会有用。

  1. Forms身份证明也能铺排模拟功效,但只可以模拟二个Windows帐户。 4.
    大多数景色下是不须求效法的。

回到顶部

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

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

澳门葡京备用网址 35

那时候,需要大家输入Windows的登录帐号,然后提交IIS验证身份。

第二遍弹出那几个对话框很符合规律:因为程序要表明用户的地位。
然而,每便关闭浏览器下次再一次打开页面时,又会冒出此对话框,此时感到就很不便宜了。
固然有点浏览器能记住用户名和密码,但本身意识FireFox,Opera,Chrome依然会弹出那些对话框,等待大家点击鲜明,
唯有Safari才不会骚扰用户直接打开网页。
IE的格外“记住笔者的密码”复选框完全是个摆放,它根本不会记住密码!

于是,笔者所试过的有所浏览器中,唯有Safari是最人性化的。
即便在暗许情况下,固然IE不会铭记密码,每一趟都亟需重新输入。
不过,IE却得以支持不晋升用户输入登录帐号而直白打开网页, 此时IE将应用用户的当前Windows登录帐号传递给IIS验证身份。

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

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

在那多少个规格中,如若网站是在多少个Windows域中运作,除了第二条大概不满足外,其余条件应该都简单满意(第5条是暗中认可值)。
因而,要让IE不提醒输入登录帐号,只要确认保障第一条满意就能够了。
下边包车型客车图纸演示了哪些做到这么些布局:(注意:配置方式也合乎用域名访问的动静)

澳门葡京备用网址 36

 

其它,除了在IE中装置Intranet外,还足以在做客网站时,用电脑名代替IP地址只怕域名
那么IE始终认为是在访问Intranet内的网站,此时也不会弹出登录对话框。

在此,笔者想再啰嗦三句:
1.
IE在集成Windows身份认证时,纵然不升迁登录对话框,但是不表示不安全,它会活动传递登录凭据。
2.
那种作为唯有IE才能支撑。(此外的浏览器只是会记住密码,在贯彻上实际是不雷同的。)

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

归来顶部

在IIS中配备Windows身份评释

与利用Forms身份验证的先后区别,使用Windows身份认证的主次需求相当的布置步骤。
那几个小节将主要介绍在IIS中布局Windows身份认证,笔者将常用的IIS6和IIS7.5为例分别介绍这个布署。

IIS6的配置 请参考下图:

澳门葡京备用网址 37

 

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

澳门葡京备用网址 38

只顾:Windows身份验证是内需安装的,方法请参见下图:

澳门葡京备用网址 39

归来顶部

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

在上篇博客中,小编出现说法了哪些用代码访问贰个用到Forms身份表明的网站中的受限页面,方法是采纳CookieContainer对象收取服务端生的记名Cookie。
不过,在Windows身份认证的网站中,身份验证的经过爆发在IIS中,而且平昔不使用库克ie保存登录状态,而是供给在伸手时发送须要的身份验证音信。

在动用代码做为客户端访问Web服务器时,大家如故须求运用HttpWebRequest对象。
为了能让HttpWebRequest在走访IIS时发送须要的身份验证消息,HttpWebRequest提供叁个属性都足以形成这一个功能:

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


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

上边是自笔者准备的总体的言传身教代码(注意代码中的注释)

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

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

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

实在根本部分依然设置UseDefaultCredentials大概Credentials,代码中的二种方法是立见成效的。
那三种方式的差距:

  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身份注解的网站时,浏览器都会弹出1个对话框(左IE,右Safari):

澳门葡京备用网址 40

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

在这多少个条件中,假设网站是在一个Windows域中运营,除了第2条大概不满足外,其它条件应该都简单满意(第④条是暗中同意值)。
由此,要让IE不提醒输入登录帐号,只要确定保证第二条满意就可以了。
上边包车型大巴图形演示了怎么成功那一个布局:(注意:配置情势也符合用域名访问的状态)

澳门葡京备用网址 41

 

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

在此,笔者想再啰嗦三句: 1.
IE在集成Windows身份验证时,尽管不升迁登录对话框,不过不意味着不安全,它会自动传递登录凭据。
2.
那种作为唯有IE才能协理。(其它的浏览器只是会记住密码,在促成上实在是不均等的。)

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

回去顶部

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

在上篇博客中,小编出现说法了什么用代码访问贰个行使Forms身份验证的网站中的受限页面,方法是行使CookieContainer对象吸收服务端生的登录Cookie。
不过,在Windows身份注脚的网站中,身份验证的进度发生在IIS中,而且根本不利用Cookie保存登录意况,而是要求在央求时发送必要的身份验证音信。

在应用代码做为客户端访问Web服务器时,大家还是供给动用HttpWebRequest对象。
为了能让HttpWebRequest在访问IIS时发送要求的身份验证消息,HttpWebRequest提供三个属性都足以形成那么些作用:

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


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

上面是本身准备的一体化的以身作则代码(注意代码中的注释)

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

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

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

实质上根本部分依然安装UseDefaultCredentials也许Credentials,代码中的两种格局是行得通的。
那三种格局的异样: 1. Credentials = CredentialCache.DefaultCredentials;
表示在殡葬请求会带上当前用户的身份验证凭据。 2. UseDefaultCredentials =
true; 此方法在里面会调用前边的主意,因而与眼下的法门是均等的。 3.
Credentials = CredentialCache.DefaultNetworkCredentials; 是在.NET
2.0中引用的新办法。

至于DefaultCredentials和DefaultNetworkCredentials的更多差异,请看本人整理的表格:

Credentials属性

声明类型

实例类型

.NET支持版本

DefaultCredentials

ICredentials

SystemNetworkCredential

从1.0开始

DefaultNetworkCredentials

NetworkCredential

SystemNetworkCredential

从2.0开始

四个类别的持续关系: 1. NetworkCredential达成了ICredentials接口, 2.
SystemNetworkCredential继承自NetworkCredential。

 

在截至那篇博客此前,笔者想本身应该谢谢新蛋。
在新蛋的网络环境中,让本身学会了应用Windows身份验证。
除了多谢之外,作者明天还专门思念 fl45 那一个登录名……

 

点击那里下载示例代码

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website