简体   繁体   English

如何检查用户是否是ldap中跨域组的成员?

[英]How to check if user is a member of crossdomain group in ldap?

I have two AD domain: domain1 и domain2. 我有两个AD域:domain1和domain2。
I created group GlobalGroup inside domain1, and added another group Domain1Group inside GlobalGroup. 我在domain1内创建了组GlobalGroup,并在GlobalGroup内添加了另一个组Domain1Group。
I have two users: user1 и user2 and group Domain2Group in domain2. 我有两个用户:user1 user user2和domain2中的Domain2Group组。
Between domain1 and domain2 was set two-way trust. 在domain1和domain2之间设置了双向信任。 And I added Domain2Group in GlobalGroup. 我在GlobalGroup中添加了Domain2Group。
User1 is a member of Domain1Group, and user2 is a member of Domain2Group. User1是Domain1Group的成员,而user2是Domain2Group的成员。
So now I need to check if they both are members of GlobalGroup. 因此,现在我需要检查它们是否都是GlobalGroup的成员。

Here I found how to find if user is member of some group from another domain. 在这里,我找到了如何查找用户是否是另一个域中某个组的成员。 My function (below) works perfectly for user1. 我的功能(如下)对于user1完美地工作。 For user2 it returns false. 对于user2,它返回false。

GroupPrincipal.GetMemebers(true) will return user2, but it is very slow (minutes on prod) and I can't use it. GroupPrincipal.GetMemebers(true)将返回user2,但是它非常慢(按分钟计算),我无法使用它。

What did I miss? 我错过了什么? Is it in code or in domain's settings? 是在代码中还是在域的设置中?

Code sample: 代码示例:

private static bool IsUserInGroup(UserPrincipal user, DirectoryEntry group, bool recursive)
        {
            group.RefreshCache(new[] {"distinguishedName", "groupType"});
            var recursiveFilter = recursive ? ":1.2.840.113556.1.4.1941:" : "";
            var filter = string.Format("(member{0}={1})", recursiveFilter, user.DistinguishedName);
            var groupDN = (string)group.Properties["distinguishedName"].Value;

            if (((int)group.Properties["groupType"].Value & 8) == 0)
            {
                var groupDomainDN = groupDN.Substring(groupDN.IndexOf(",DC=", StringComparison.Ordinal));
                filter = string.Format("(|{0}(member{1}=CN={2}, CN=ForeignSecurityPrincipals{3}))", filter, recursiveFilter, user.Sid, groupDomainDN);
            }

            var searcher = new DirectorySearcher
            {
                Filter = filter,
                SearchRoot = group,
                PageSize = 1,
                SearchScope = SearchScope.Base
            };

            searcher.PropertiesToLoad.Add("cn");
            return searcher.FindOne() != null;
        }

I'm the author of that article you found. 我是您找到的那篇文章的作者。 :) :)

What is the scope of your parent group? 您的家长小组的范围是什么? You call it GlobalGroup , but Global groups cannot have members from other domains. 您将其GlobalGroup ,但是Global组不能具有来自其他域的成员。 So it must be either Universal (if the two domains are in the same AD forest) or Domain Local. 因此,它必须是通用的(如果两个域在同一个AD林中)或本地的域。 The answer will be different in each case. 在每种情况下答案都是不同的。

I will assume the two domains are not in the same forest and the group is Domain Local. 我将假定这两个域不在同一林中,并且该组是“本地域”。

The code will only return true is the external user is a direct member of the group. 该代码仅在外部用户是该组的直接成员时才返回true。

If you use that code to check if Domain2Group is a member of GlobalGroup , it would return true . 如果您使用的代码,以检查是否Domain2Group是成员GlobalGroup ,它将返回true But when you use it to check if user2 is a member, it's not looking inside Domain2Group to see if the user is there. 但是,当您使用它检查user2是否为成员时,它并没有在Domain2Group内部查看用户是否在那里。

This is something I should address, so I have updated the code in my article. 这是我应该解决的问题,因此我更新了文章中的代码。 We can use the tokenGroups attribute of the user to get a recursive list of all groups the user is in. That gives us a list of SIDs. 我们可以使用用户的tokenGroups属性来获取用户所在的所有组的递归列表。这将为我们提供SID列表。 So we can use that to look for any of those groups in our parent group on the other domain. 因此,我们可以使用它在另一个域的父组中查找那些组。

I see you have your user object as a UserPrincipal . 我看到您将user对象作为UserPrincipal To pass it into this method, you can use user.GetUnderlyingObject() , like this: 要将其传递给此方法,可以使用user.GetUnderlyingObject() ,如下所示:

IsUserInGroup((DirectoryEntry) user.GetUnderlyingObject(), group, true)

Here is the updated method: 这是更新的方法:

private static bool IsUserInGroup(DirectoryEntry user, DirectoryEntry group, bool recursive) {

    //fetch the attributes we're going to need
    user.RefreshCache(new [] {"distinguishedName", "objectSid"});
    group.RefreshCache(new [] {"distinguishedName", "groupType"});

    //This magic number tells AD to look for the user recursively through any nested groups
    var recursiveFilter = recursive ? ":1.2.840.113556.1.4.1941:" : "";

    var userDn = (string) user.Properties["distinguishedName"].Value;
    var groupDn = (string) group.Properties["distinguishedName"].Value;

    var filter = $"(member{recursiveFilter}={userDn})";

    if (((int) group.Properties["groupType"].Value & 8) == 0) {
        var groupDomainDn = groupDn.Substring(
            groupDn.IndexOf(",DC=", StringComparison.Ordinal));
        var userDomainDn = userDn.Substring(
            userDn.IndexOf(",DC=", StringComparison.Ordinal));
        if (groupDomainDn != userDomainDn) {
            //It's a Domain Local group, and the user and group are on
            //different domains, so the account might show up as a Foreign
            //Security Principal. So construct a list of SID's that could
            //appear in the group for this user
            var fspFilters = new StringBuilder();

            var userSid =
                new SecurityIdentifier((byte[]) user.Properties["objectSid"].Value, 0);
            fspFilters.Append(
                $"(member{recursiveFilter}=CN={userSid},CN=ForeignSecurityPrincipals{groupDomainDn})");

            if (recursive) {
                //Any of the groups the user is in could show up as an FSP,
                //so we need to check for them all
                user.RefreshCache(new [] {"tokenGroupsGlobalAndUniversal"});
                var tokenGroups = user.Properties["tokenGroupsGlobalAndUniversal"];
                foreach (byte[] token in tokenGroups) {
                    var groupSid = new SecurityIdentifier(token, 0);
                    fspFilters.Append(
                        $"(member{recursiveFilter}=CN={groupSid},CN=ForeignSecurityPrincipals{groupDomainDn})");
                }
            }
            filter = $"(|{filter}{fspFilters})";
        }
    }

    var searcher = new DirectorySearcher {
        Filter = filter,
        SearchRoot = group,
        PageSize = 1, //we're only looking for one object
        SearchScope = SearchScope.Base
    };

    searcher.PropertiesToLoad.Add("cn"); //just so it doesn't load every property

    return searcher.FindOne() != null;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM