我有一个使用 Windows 身份验证的 ASP.Net MVC 应用程序,并且我正在检查组成员身份以了解控制器操作的安全性。
听起来很简单,但我发现没有其他问题可以解决我遇到的问题。
第一次尝试:[授权]
经典的方法是简单地Authorize
在控制器动作上打一个数据注释属性然后去城里:
[Authorize(Roles = @"domain\groupName1")]
没有骰子。系统提示我输入凭据。通常这意味着 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");
难住了......所以我找了我的系统书呆子,我们仔细检查了一切。用户是组成员?是的。组名拼写正确?是的。下一步是抓住 SID。
第三次尝试:搜索身份的组集合
在我的控制器中,我检查WindowsIdentity
并查看有问题的组的 SID 的组集合:
var wi = (WindowsIdentity)wp.Identity;
var group = wi.Groups.SingleOrDefault(g => g.Value == "group1-sidValue");
group
变量是SecurityIdentifier
对象。因为它不为空,所以我们可以确定这个当前用户是该组的成员,[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");
两个组主体变量都具有相同的对象,并且我通过监视变量验证主体的Members
集合包含与当前onUserPrincipal
具有相同 SID 的对象。WindowsPrincipal
HttpContext
问题:
我到底错过了什么?当通过对象探索清楚地表明用户是该给定组的有效成员时,为什么两种角色检查方法都会失败?
一组检查正常而另一组检查的事实在这一点上似乎不是最奇怪的部分。