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

时间:2011-11-15 19:37:50

标签: c# active-directory

与以下MSDN主题中的问题类似:http://social.msdn.microsoft.com/Forums/en-MY/csharplanguage/thread/4c9fea6c-1d0a-4733-a8ac-e3b78d10e999

我正在尝试验证给定用户是否是某个组的成员,而我们现有的功能解决方案太慢(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的成员。 Sam是GroupChild的成员。如果我在(Steve,GroupParent)上调用此函数,则返回true。如果我打电话给它(Sam,GroupParent),我会收到一个错误。如果我打电话给它(“fdkjskghkf”,GroupParent),则返回false。

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

5 个答案:

答案 0 :(得分:5)

感谢Jon Theriault here,以下代码为我解决了这个问题。

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);

答案 1 :(得分:2)

我记得当我编写类似的代码时,我遇到了一些奇怪的问题。我不确定为什么你的电话会失败,但你可以解决你的问题,并做一些类似的事情:

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

答案 2 :(得分:0)

你可以尝试这样的事情:

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));
} 

答案 3 :(得分:0)

如果有人有兴趣。使用带有以下过滤器的DirectorySearcher大约快60%。

string filter = string.Format(“(&amp;(distinguishedName = {1})(memberof:1.2.840.113556.1.4.1941:= {0}))”,dnOfUser,dnOfGroup);

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

答案 4 :(得分:0)

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;
}

使用Try / Catch,因为我在一个非常大的AD(50万个对象)中有200个组中的2个有一些例外,因为我的一些SID(Translate做SID - &gt;名称转换)不再可用。 在我们庞大的AD中只需要&lt; 1秒。