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

发布于 2024-12-15 10:31:08 字数 1353 浏览 1 评论 0原文

类似于以下 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。

我在上面链接了一篇有类似问题的文章,但他的解决方案对我不起作用,我仍然遇到同样的错误。有想法吗?

Similar to the problem in the following MSDN thread: http://social.msdn.microsoft.com/Forums/en-MY/csharplanguage/thread/4c9fea6c-1d0a-4733-a8ac-e3b78d10e999

I am trying to verify whether or not a given user is a member of a group, and our existing functional solutions are too slow (13-16 seconds) and I'm trying to speed it up. I currently have:

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

What makes this interesting is that it only returns an error when the user is not in the group directly, but rather a member of a group that is within the target group.

For example:

Steve and Sam are two users, and GroupParent and GroupChild are two groups. Steve and GroupChild are members of GroupParent. Sam is a member of GroupChild. If I call this function on (Steve, GroupParent), it returns true. If I call it on (Sam, GroupParent), I get an error. If I call it on ("fdkjskghkf", GroupParent) it returns false.

I linked an article above with similar issues, but his solution did not work for me, I still got the same error. Ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

葬花如无物 2024-12-22 10:31:08

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

Thanks to Jon Theriault here the following code fixed this problem for me.

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);
半城柳色半声笛 2024-12-22 10:31:08

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

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

I remember when I wrote similar code I did run into some strange issues. I'm not sure exactly why your call is failing but you can turn your problem around and do something like:

return group.GetMembers(true).Contains(user);
暮色兮凉城 2024-12-22 10:31:08

你能尝试这样的事情吗:

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

Can you try somethig like this :

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));
} 
小清晰的声音 2024-12-22 10:31:08

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

字符串过滤器 = string.Format("(&(distinguishedName={1})(memberof:1.2.840.113556.1.4.1941:={0}))", dnOfUser, dnOfGroup);

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

If anyone is interested. Using DirectorySearcher with the following filter is approx 60% faster.

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

The filter will traverse upwards and not just the parent of the user.

檐上三寸雪 2024-12-22 10:31:08

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(翻译确实) SID -> 名称转换)不再可用。
在我们庞大的广告中只需要< 1秒。

GetAuthorizationGroups() does not find nested groups.

To really got all groups a given user is member of included nested groups try this:

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

Use Try/Catch because I had some exceptions in a very large AD (half a million objects) with 2 out of 200 groups because my some SIDs (Translate does SID -> Name conversion) were no longer available.
In our huge AD is only takes < 1 second.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文