帮助!我一直在尝试编写一个函数来确认用户在Active Directory组中的成员资格,并且如果该成员恰好在该组中,它会起作用,如果该用户不在,则会抛出异常。
这是功能:
private bool IsUserMemberOfGroup(string user, string group)
{
using (var ctx = new PrincipalContext(ContextType.Domain))
using (var groupPrincipal = GroupPrincipal.FindByIdentity(ctx, group))
using (var userPrincipal = UserPrincipal.FindByIdentity(ctx, user))
{
if (groupPrincipal == null)
{
return false;
}
else
{
return userPrincipal.IsMemberOf(groupPrincipal);
}
}
}
这是YSOD:
描述:执行当前Web请求期间发生了未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的更多信息。
异常详情:
System.Runtime.InteropServices.COMException:未知错误(0x80005000)
来源错误:
Line 34: else
Line 35: {
Line 36: return userPrincipal.IsMemberOf(groupPrincipal);
Line 37: }
Line 38: }
我不知道它是否相关,但是当我单步执行该函数时,groupPrincipal.Members.Count抛出类型为“System.NullReferenceException”的异常,Count.Base显示一个异常,并显示消息“Object reference not not设置为对象的实例“。
到底发生了什么事?当某人不是会员时,为什么名为IsMemberOf的bool不会返回false?
谢谢,
丹尼尔
答案 0 :(得分:4)
我认为你可以简化一些事情:
private bool IsUserMemberOfGroup(string user, string group)
{
using (var ctx = new PrincipalContext(ContextType.Domain))
using (var userPrincipal = UserPrincipal.FindByIdentity(ctx, user))
{
PrincipalSearchResult<Principal> result = userPrincipal.GetGroups();
GroupPrincipal groupPrincipal =
result.Where(g => g.SamAccountName == groupName).FirstOrDefault();
return (groupPrincipal != null);
}
}
userPrincipal.GetGroups()
将为您提供该用户的所有组成员身份(包括主要组和嵌套组成员身份)的明确列表;然后搜索您感兴趣的群组的列表,例如通过samACcountName或其他一些属性。
如果您在PrincipalSearchResult<Principal>
返回的GetGroups()
中找到了您要查找的群组,那么您的用户就是该群组的成员。
您可以使用此功能为自己保存至少一个“FindByIdentity”。
答案 1 :(得分:1)
对marc_s的代码进行了一次小修改,我有:
using (var ctx = new PrincipalContext(ContextType.Domain))
using (var userPrincipal = UserPrincipal.FindByIdentity(ctx, user))
using (var groupPrincipal = GroupPrincipal.FindByIdentity(ctx, group))
{
if (userPrincipal == null) return false;
if (groupPrincipal == null) return false;
PrincipalSearchResult<Principal> result = userPrincipal.GetGroups();
Principal grp = result.Where(g => g.Sid == groupPrincipal.Sid).FirstOrDefault();
return (grp != null);
}
比较Sid似乎比比较SamAccountName更可靠。
答案 2 :(得分:0)
我们的设置中有一些毒药组导致某些用户失败而其他用户失败。其他建议答案中的“FirstOrDefault”逻辑可能帮助我们躲避毒药群,但这并不能保证。
对于遇到此问题的其他人,我们有两条建议。首先检查组名中是否有任何带正斜杠的组(实际的组名,而不是“pre-windows 2000”名称,它将用下划线替换它)。如果您可以重命名可能解决问题的所有此类组...它对我们有用。
这种解决方法也适用于我们:
/// <summary>
/// This does a recursive group search for the given user or computer principal.
/// </summary>
public IEnumerable<Principal> GetGroups(Principal principal)
{
return GetGroups(null, principal);
}
private IEnumerable<Principal> GetGroups(HashSet<SecurityIdentifier> ancestorPrincipalSids, Principal parentPrincipal)
{
try
{
//enumerate this here so errors are thrown now and not later
//if the current group name has a forward-slash, I think this
//will always error here
var groups = parentPrincipal.GetGroups().ToArray();
if (groups == null)
{
return Enumerable.Empty<Principal>();
}
//keep track of all ancestors in the group hierarchy to this point
//so that we can handle circular references below
var newAncestors = new HashSet<SecurityIdentifier>(ancestorPrincipalSids ?? Enumerable.Empty<SecurityIdentifier>());
newAncestors.Add(parentPrincipal.Sid);
return groups
.Concat(groups
.Where(g => !newAncestors.Contains(g.Sid)) //handle circular references
.SelectMany(g => GetGroups(newAncestors, g)));
}
catch
{
return Enumerable.Empty<Principal>();
}
}