C#System.DirectoryServices.AccountManagement未知错误(0x80005000)UserPrincipal.IsMemberOf()

C#System.DirectoryServices.AccountManagement未知错误(0x80005000)UserPrincipal.IsMemberOf(),c#,active-directory,C#,Active Directory,类似于以下MSDN线程中的问题: 我正在尝试验证给定用户是否是组的成员,我们现有的功能解决方案太慢(13-16秒),我正在尝试加快速度。我目前有: public bool IsMemberAD(string userName, string groupName) { var pc = new System.DirectoryServices.AccountManagement.PrincipalContext(System.DirectoryServices.AccountManagem

类似于以下MSDN线程中的问题:

我正在尝试验证给定用户是否是组的成员,我们现有的功能解决方案太慢(13-16秒),我正在尝试加快速度。我目前有:

public bool IsMemberAD(string userName, string groupName)
{
    var pc = new System.DirectoryServices.AccountManagement.PrincipalContext(System.DirectoryServices.AccountManagement.ContextType.Domain);
    var user = System.DirectoryServices.AccountManagement.UserPrincipal.FindByIdentity(pc, System.DirectoryServices.AccountManagement.IdentityType.SamAccountName,
                                                 userName.ToLower());
    var group = System.DirectoryServices.AccountManagement.GroupPrincipal.FindByIdentity(pc, groupName);

    if (group == null || user == null) return false;

    return user.IsMemberOf(group);    
}
有趣的是,它只在用户不直接在组中,而是在目标组中的组的成员时返回错误

例如:

Steve和Sam是两个用户,GroupParent和GroupChild是两个组。Steve和GroupChild是GroupParent的成员。山姆是GroupChild的成员。如果我在(Steve,GroupParent)上调用此函数,它将返回true。如果我打开它(Sam,GroupParent),我会得到一个错误。如果我调用它(“fdkjskghkf”,GroupParent),它将返回false


我将上面的一篇文章与类似的问题联系起来,但他的解决方案对我不起作用,我仍然得到了同样的错误。想法?

我记得当我编写类似的代码时,我确实遇到了一些奇怪的问题。我不确定您的呼叫失败的确切原因,但您可以扭转您的问题并执行以下操作:

return group.GetMembers(true).Contains(user);

你能试试这样的东西吗

public bool IsMemberAD(string userName, string groupName)
{
  PrincipalContext context = new PrincipalContext(ContextType.Domain, "WM2008R2ENT:389", "dc=dom,dc=fr", "jpb", "pwd");

  /* Retreive the user principal
   */
  UserPrincipal user = UserPrincipal.FindByIdentity(context, userName);
  if (user == null) return false;

  /* Retreive the group principal
   */
  GroupPrincipal targetGroup = GroupPrincipal.FindByIdentity(context, groupName);
  if (targetGroup == null) return false;

  /* Look for all the groups a user belongs to
   */
  PrincipalSearchResult<Principal> allGroups = user.GetAuthorizationGroups();

  var grp = (from g in allGroups
             where g.Sid == targetGroup.Sid
             select g).FirstOrDefault();

  return (!(grp == null));
} 
public bool IsMemberAD(字符串用户名、字符串组名)
{
PrincipalContext上下文=新PrincipalContext(ContextType.Domain,“WM2008R2ENT:389”,“dc=dom,dc=fr”,“jpb”,“pwd”);
/*检索用户主体
*/
UserPrincipal user=UserPrincipal.FindByIdentity(上下文,用户名);
如果(user==null)返回false;
/*检索组负责人
*/
GroupPrincipal targetGroup=GroupPrincipal.FindByIdentity(上下文,groupName);
if(targetGroup==null)返回false;
/*查找用户所属的所有组
*/
PrincipalSearchResult allGroups=user.GetAuthorizationGroups();
var grp=(来自所有组中的g)
其中g.Sid==targetGroup.Sid
选择g).FirstOrDefault();
返回(!(grp==null));
} 
多亏了Jon Theriault,下面的代码为我解决了这个问题

string strName = System.Security.Principal.WindowsIdentity.GetCurrent().Name; // "MW\\dalem"
// This is here because of a .Net error that gets 0x80005000 on "isUser = user.IsMemberOf(groupU);"
string domainName = strName.Split('\\')[0]; 
var pc = new PrincipalContext(ContextType.Domain, domainName);

如果有人感兴趣。将DirectorySearcher与以下筛选器一起使用大约快60%

string filter=string.Format(&(differentizedName={1})(memberof:1.2.840.113556.1.4.1941:={0})),dnOfUser,dnOfGroup)

筛选器将向上遍历,而不仅仅是用户的父级。

GetAuthorizationGroups()未找到嵌套组

要真正获取给定用户是包含的嵌套组成员的所有组,请尝试以下操作:

using System.Security.Principal

private List<string> GetGroups(string userName)
{
    List<string> result = new List<string>();
    WindowsIdentity wi = new WindowsIdentity(userName);

    foreach (IdentityReference group in wi.Groups)
    {
        try
        {
            result.Add(group.Translate(typeof(NTAccount)).ToString());
        }
        catch (Exception ex) { }
    }

    result.Sort();
    return result;
}
使用System.Security.Principal
私有列表GetGroups(字符串用户名)
{
列表结果=新列表();
WindowsIdentity wi=新的WindowsIdentity(用户名);
foreach(wi.Groups中的IdentityReference组)
{
尝试
{
Add(group.Translate(typeof(NTAccount)).ToString());
}
捕获(例外情况除外){}
}
result.Sort();
返回结果;
}
使用Try/Catch是因为我的一些SID(Translate does SID->Name conversion)不再可用,所以在一个非常大的广告(50万个对象)中,200个组中有2个组出现了一些异常。
在我们的大型广告中,只需<1秒钟。

这在技术上是可行的,但速度非常慢。我发布的代码(当它没有中断时)大约在1.5秒内完成,但返回“group.GetMembers(true).Contains(user);”需要10秒。我想这与递归检查有关?我想这取决于你的广告的大小和复杂性。我在一家中型公司工作,两个查询都会在一秒钟内返回。