问题描述
我有一个使用 Windows 身份验证的 ASP.Net MVC 应用程序,我正在检查组成员身份以确保控制器操作的安全性.
I have an ASP.Net MVC application using Windows Authentication, and I am checking group membership for security on controller actions.
听起来很简单,但我发现没有其他问题可以解决我遇到的问题.
Simple as it sounds, I've found no other Question that can resolve the problem I am experiencing.
经典的方法是简单地在控制器动作上加上一个Authorize
数据注释属性然后去镇上:
The classic method is to simply slap an Authorize
data annotation attribute on the controller action and go to town:
[Authorize(Roles = @"domaingroupName1")]
没有骰子.系统提示我输入凭据.通常这意味着 Windows 身份验证配置有问题,但它设置得很好:(1) HttpContext.User
是一个 WindowsPrincipal
对象,(2) 我确认了另一个已知组名称有效.
No dice. I am prompted for credentials. Usually this means something is wrong with the Windows Authentication configuration but it's setup fine: (1) HttpContext.User
is a WindowsPrincipal
object, and (2) I confirmed another known group name works.
采取的下一步是走更老式的路线并使用 IPrincipal.IsInRole()
,同样,一个返回 false
,另一个返回 true
.
The next step taken was to go a more old fashioned route and use IPrincipal.IsInRole()
, and again, one returns false
, the other true
.
var wp = (WindowsPrincipal)User;
// false
var inGroup1 = wp.IsInRole(@"domaingroupName1");
// true
var inGroup2 = wp.IsInRole(@"domaingroupName2");
难倒...所以我联系了我的系统书呆子,我们仔细检查了一切.用户是群组成员?是的.组名拼写正确吗?是的.下一步是获取 SID.
Stumped... so I hit up my systems nerds and we double check everything. User is a group member? Yes. Group name is spelled correctly? Yes. The next step was to snag the SID.
在我的控制器中,我检查 WindowsIdentity
并查看组集合以查找麻烦组的 SID:
In my controller I check the WindowsIdentity
and look through the group collection for the SID of the troublesome group:
var wi = (WindowsIdentity)wp.Identity;
var group = wi.Groups.SingleOrDefault(g => g.Value == "group1-sidValue");
group
变量是 SecurityIdentifier
对象.因为它不为空,我们可以确定这个当前用户是 [Authorize()]
或 IsInRole()
尝试都未能确认的组的成员.
The group
variable is the SecurityIdentifier
object. Because it is not null, we can be certain that this current user is a member of the group that both the [Authorize()]
or IsInRole()
attempts fail to confirm.
此时,我要发疯并添加对 AccountManagement API 的引用.我通过名称和 SID 在域上下文中搜索 GroupPrincipal
:
At this point, I'm going nuts and add reference to the AccountManagement APIs. I search the domain context for the GroupPrincipal
by both name and SID:
var pc = new PrincipalContext(ContextType.Domain, "domain");
var gp1byName = GroupPrincipal.FindByIdentity(pc, "groupName1")
var gp1bySid = GroupPrincipal.FindByIdentity(pc, IdentityType.Sid, "group1-sidValue");
两个组主体变量都具有相同的对象,并且我通过监视变量验证了主体的 Members
集合包含一个与 SID 相同的 UserPrincipal
对象HttpContext
上的当前 WindowsPrincipal
.
Both group principal variables are ripe with the same object, and I verified through a watch variable that the principal's Members
collection contains a UserPrincipal
object with the same SID as the current WindowsPrincipal
on HttpContext
.
我到底错过了什么?当通过对象探索清楚地表明用户是该给定组的有效成员时,为什么这两种角色检查方法都会失败?
What in the hell have I missed here? Why would both role checking methodologies fail when it is plain and clear through object exploration that the user is a valid member of this given group?
一组检查正常而另一组检查的事实在这一点上似乎并不是最奇怪的部分.
The fact that one group checks fine and the other does not seems the most strange part at this point.
推荐答案
答案:
本质上是 WindowsIdentity
和 NTAccount
(两者都是 System.Security.Principal)之间的转换问题,最后是实际的 Active Directory 条目.
Answer:
Essentially it's translation issues between WindowsIdentity
and NTAccount
(both of these System.Security.Principal) and lastly, the actual Active Directory entry.
针对 AD 验证 WindowsIdentity
时,如果您想使用 Sam 或 Sid 以外的任何内容,则需要使用 System.DirectoryServices.AccountManagement
.
When validating a WindowsIdentity
against AD, if you want to use anything other than the Sam or the Sid, you will need to use System.DirectoryServices.AccountManagement
.
警告:在 .Net 4.5 中,安全主体包括 Claims,但这与上下文无关.
在 Windows Authenticated Web 应用程序中,HttpContext.User
是一个包裹底层 WindowsIdentity
的 WindowsPrincipal
对象.
In a Windows Authenticated web application, HttpContext.User
is a WindowsPrincipal
object wrapping an underlying WindowsIdentity
.
WindowsIdentity
对于大多数意图和目的,只有两个属性可以识别经过身份验证的用户:Name
和 User
.
WindowsIdentity
has for most intents and purposes only two properties with which the authenticated user can be identified: Name
and User
.
这些属性转换为身份对应的 AD 帐户条目上的两个属性:
These properties translate to two properties on the identity's corresponding AD account entry:
WindowsIdentity.Name
= SamAccountName
WindowsIdentity.User
= SID
[Authorize]
过滤器属性最终会调用底层主体上的 IsInRole(string role)
...和 IsInRole()
字符串重载使用 role
(AD 条目中的SamAccountName")实例化 NTAccount
.
The [Authorize]
filter attribute ultimately calls IsInRole(string role)
on the underlying principal... and the IsInRole()
string overload instantiates an NTAccount
with the role
(the "SamAccountName" in an AD entry).
这解释了上面 #1 和 #2 中的失败.
This explains the failure in #1 and #2 above.
要针对除他/她的 Sid 或 SamAccountName 之外的任何内容授权 HttpContext.User
,您需要 DirectoryServices.AccountManagement
或经典 LDAP.
To authorize the HttpContext.User
against anything but his/her Sid or SamAccountName, you'll need DirectoryServices.AccountManagement
or classic LDAP.
这篇关于.Net 4.5 中的 Active Directory 组成员身份检查的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!