在.Net 4.5中检查Active Directory组成员身份

one*_*mer 7 .net c# security asp.net-mvc active-directory

我有一个使用Windows身份验证的ASP.Net MVC应用程序,我正在检查组成员身份以确保控制器操作的安全性.

听起来很简单,我发现没有其他问题可以解决我遇到的问题.

第一次尝试:[授权]

经典的方法是简单地Authorize在控制器动作上打一个数据注释属性并转到城镇:

[Authorize(Roles = @"domain\groupName1")]
Run Code Online (Sandbox Code Playgroud)

没有骰子.我被提示输入凭据.通常这意味着Windows身份验证配置有问题,但设置正常:(1)HttpContext.User是一个WindowsPrincipal对象,(2)我确认另一个已知的组名有效.

第二次尝试:IsInRole()

采取的下一步是采用更老式的路线并使用IPrincipal.IsInRole(),再一次,一个返回false,另一个true.

var wp = (WindowsPrincipal)User;

// false
var inGroup1 = wp.IsInRole(@"domain\groupName1");
// true
var inGroup2 = wp.IsInRole(@"domain\groupName2");
Run Code Online (Sandbox Code Playgroud)

难倒...所以我打了我的系统书呆子,我们仔细检查一切.用户是群组成员?是.组名拼写正确吗?是.下一步是阻止SID.

第三次尝试:搜索身份的群集

在我的控制器中,我检查WindowsIdentity并查看组集合中的麻烦组的SID:

var wi = (WindowsIdentity)wp.Identity;
var group = wi.Groups.SingleOrDefault(g => g.Value == "group1-sidValue");
Run Code Online (Sandbox Code Playgroud)

group变量是SecurityIdentifier对象.因为它不是null,所以我们可以确定当前用户是这两个[Authorize()]或两个IsInRole()尝试都无法确认的组的成员.

第四次尝试:DirectoryServices.AccountManagement

在这一点上,我疯了,并添加了对AccountManagement API的引用.我在域上下文中搜索GroupPrincipal名称和SID:

   var pc = new PrincipalContext(ContextType.Domain, "domain");
   var gp1byName = GroupPrincipal.FindByIdentity(pc, "groupName1")
   var gp1bySid = GroupPrincipal.FindByIdentity(pc, IdentityType.Sid, "group1-sidValue");
Run Code Online (Sandbox Code Playgroud)

两个组主变量都是成熟的同一个对象,我通过一个监视变量验证了主体的Members集合包含一个UserPrincipal与当前WindowsPrincipal开启的SID相同的对象HttpContext.

题:

我到底在这里错过了什么?当通过对象探索明确且清楚地表明用户是该给定组的有效成员时,为什么两种角色检查方法都会失败?

事实上,一组检查正常,另一组在这一点上似乎不是最奇怪的部分.

one*_*mer 5

回答:

本质上,它是WindowsIdentityNTAccount(这两个 System.Security.Principal)之间的转换问题,最后是实际的 Active Directory 条目。

WindowsIdentity针对 AD验证 a时,如果您想使用 Sam 或 Sid 以外的任何内容,则需要使用System.DirectoryServices.AccountManagement.

警告:在 .Net 4.5 中,安全主体包括 Claims,但这与上下文无关。


长解释:

在 Windows Authenticated Web 应用程序中,HttpContext.User是一个WindowsPrincipal包装底层WindowsIdentity.

WindowsIdentity对于大多数意图和目的,只有两个属性可以识别经过身份验证的用户:NameUser.

这些属性转换为身份对应的 AD 帐户条目上的两个属性:

WindowsIdentity.Name = SamAccountName

WindowsIdentity.User = SID

[Authorize]过滤器属性最终调用IsInRole(string role)底层的主要上...和IsInRole()串过载实例化NTAccount与所述role(下称“Sam帐户”在AD条目)。

这解释了上面#1 和#2 中的失败。

HttpContext.User针对除他/她的 Sid 或 SamAccountName 之外的任何内容进行授权,您需要使用DirectoryServices.AccountManagementLDAP 或经典 LDAP。