获取用户所属的所有组

时间:2014-12-30 09:48:28

标签: c# .net active-directory ldap directoryservices

域A和域B有两个域,它们之间具有相互信任(林级信任)。

'DomainA \ BiggerGroup'是域A中的用户组(域本地范围)。

'DomainB \ SmallGroup'是域B中的用户组(全局范围)。

DomainA \ BigGroup包含DomainB \ SmallGroup作为子组。 DomainB \ SmallGroup包含DomainB \ User作为成员。

查询:

作为DomainB的管理员,我们能否以编程方式列出DomainB \ User所属的所有组?

WindowsIdentity.Groups未枚举DomainA \ BiggerGroup。有没有什么方法可以列出用户所属的所有组(包括受信任域中的组)?

(WindowsIdentity Class具有Group属性,“获取当前Windows用户所属的组。” - http://msdn.microsoft.com/en-us/library/system.security.principal.windowsidentity(v=vs.110).aspx

3 个答案:

答案 0 :(得分:1)

当您正在处理两个域之间具有林级别信任的域时。我认为您可以使用WindowsIdentity.Groups再次尝试,但是使用全局编录(GC)目录建立连接(主要上下文),而不管任何其他DC目录。

答案 1 :(得分:1)

严格地说,用户登录到不同的域时可能会有不同的组列表。 这是因为域名本地群组仅限于群组自己的域(顾名思义)。

在你的情况下:

  • 当DomainB \ User登录到DomainA时,组列表包含DomainA \ BiggerGroup和DomainB \ SmallGroup
  • 当DomainB \ User登录到DomainB时,组列表包含DomainB \ SmallGroup

通常,用户的组列表将包含:

  1. Global&来自USER域的通用组(在您的情况下为DomainB),加上
  2. 来自连接域的域本地组
    (如果您正在登录计算机,则为COMPUTER域)
  3. 其他知名团体,如“Authenticated Users”,“Everyone”
    (如果您只对AD组感兴趣,可以忽略这一点)
  4. 那么,w.r.t您要查找哪个域名的DomainB \ User?


    解决方案:

    要获取用户的准确组列表(不提供该用户的密码),您可以使用S4U Kerberos Extensions。 (参见下面链接中的S4U2Self部分)

    http://msdn.microsoft.com/en-us/magazine/cc188757.aspx

    该链接建议使用WindowsIdentity。但是WindowsIdentity解决方案有一个问题。

    // parameter must be in upn format
    WindowsIdentity identity = new WindowsIdentity("User@DomainB.com");
    

    问题是您无法控制从哪个域获取域本地组 例如在加入DomainA的计算机上,以DomainB中的用户身份登录,在DomainC中获取用户的WindowsIdentity。它将从域A,B或C获得域本地组?

    或者您可以使用链接中提到的LsaLogonUser Win32函数。但它需要14个参数......
    我之前从未尝试过,不能对此发表评论。

答案 2 :(得分:0)

您需要为用户获取令牌组。由于嵌套(包括其他域),它将返回所有直接和间接的有效gorup成员资格。

    // this method will return all groups where the the user is a direct and indirect member of
    public static bool getTokenGroups(string domainFQDN, string alias, ref List<string> userGroups)
    {
        bool result = false;

        try
        {
            SearchResult sr = default(SearchResult);
            using (DirectoryEntry domainDE = new DirectoryEntry("LDAP://" + domainFQDN, "domain\\cn", "password", AuthenticationTypes.Secure))
            {
                using (DirectorySearcher searcher = new DirectorySearcher(domainDE))
                {
                    searcher.Filter = String.Format("(&(objectClass=user)(sAMAccountName={0}))", alias);
                    sr = searcher.FindOne();

                    if (sr != null)
                    {

                        using (DirectoryEntry user = sr.GetDirectoryEntry())
                        {
                            user.RefreshCache(new string[] { "tokenGroups" });

                            for (int i = 0; i < user.Properties["tokenGroups"].Count; i++)
                            {
                                SecurityIdentifier sid = new SecurityIdentifier((byte[])user.Properties["tokenGroups"][i], 0);
                                NTAccount nt = (NTAccount)sid.Translate(typeof(NTAccount));
                                //do something with the SID or name (nt.Value)
                                if(nt.Value.IndexOf('\\') > -1)
                                    userGroups.Add(nt.Value.Split('\\')[1]);
                                else
                                    userGroups.Add(nt.Value);
                            }
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            EventLog.WriteEntry("source name", MethodBase.GetCurrentMethod().DeclaringType + "." + MethodBase.GetCurrentMethod().Name + "\r\n\r\nUnable to get user's token groups for domain: " + domainFQDN + " user: " + alias + "\r\n\r\n" + ex.Message, EventLogEntryType.Error);
        }

        return result;
    }