簡體   English   中英

如何獲取屬於本地系統組的域用戶 SID

[英]how to get domain user SID which is part of local system group

我在域(沒有工作組)中有一台機器,我有一個本地組Test Users ,在這個組中我添加了域用戶。

域\\管理員

域\\安裝

在此處輸入圖片說明

現在我想從組中獲取所有用戶以及他們的SID 使用下面的代碼,我可以獲取該組中的所有用戶名,但是如何獲取SID呢?

using (var groupEntry = new DirectoryEntry("WinNT://./Test Users,group"))
            {
                foreach (var member in (IEnumerable)groupEntry.Invoke("Members"))
                {
                    using (var memberEntry = new DirectoryEntry(member))
                    {
                        Console.WriteLine(memberEntry.Name);
                    }
                }
            }

替代解決方案

你問是否有另一種方法,為此我發布了一個不同的過程來查找帳戶的 SID。 使用包管理器獲取 nuget 包: System.DirectoryServices.AccountManagement

自從 MS 與System.DirectoryServices.AccountManagement一起出現以來,我幾乎用該程序集編寫了所有 AD 工作。 以下是我為查找系統本地組中組/帳戶所有成員的 SID 的不同方式編寫的代碼。

    // Recursively looks up all members and returns All the SIDs of all 'User' or 'local' accounts. 
    // ---> (NOT GROUPS but you can change that if you'd like.)
    private static List<string> GetSidsForAllAccounts(GroupPrincipal grp)
    {
        List<string> listOfSids = new List<string>();
        foreach (var member in grp.Members)
        {
            if (member.StructuralObjectClass != null && member.StructuralObjectClass.ToLower().Equals("group"))
                listOfSids.AddRange(GetSidsForAllAccounts((GroupPrincipal)member));
            else
                listOfSids.Add(member.Sid.ToString());
                // You could also use below to get Name and SID, PIPE delimited.
                // listOfSids.Add($"{member.Name}|{member.Sid.ToString()}");
                // You'll have to cast member to UserPrincipal if you are looking for properties specific to User Account.
        }
        return listOfSids;
    }

在 main 方法中使用:您可以通過以下方式調用上述方法。

    // Look up the definition of PrincipalContext to use credentials.
    // e.g. new PrincipalContext(ContextType.Machine, "domainName", "user", "pass");
    PrincipalContext local = new PrincipalContext(ContextType.Machine);
    GroupPrincipal grp = GroupPrincipal.FindByIdentity(local, "Administrators");

    List<string> allSids = GetSidsForAllAccounts(grp);
    allSids.ForEach(x => Console.WriteLine(x));

這是如何運作的

  1. PrincipalContext定義在何處查找第一組,在本例中為“本地機器”。
  2. 在查找詳細信息時,循環遍歷每個組使用組本身的PrincipalContext 如果該組屬於域,它將使用域上下文自動查找,如果它是本地機器組,它將使用本地機器。
  3. 遞歸地遍歷每個組以查找其成員,直到其所有用戶帳戶。

要獲得 DirectoryEntry 的 SID,您必須獲得用戶/組的擴展屬性。 您可以通過在 DirectoryEntry 上調用.Properties來獲取這些屬性。 您可以使用["propertyName"].Value訪問每個屬性,但對於 SID,您必須將 SID 的字節數組轉換為字符串。 下面是來自 codeproject 站點的轉換方法以及如何使用它。

將字節轉換為字符串的方法取自here

    private static string ConvertByteToStringSid(Byte[] sidBytes)
        {
            StringBuilder strSid = new StringBuilder();
            strSid.Append("S-");
            try
            {
                // Add SID revision.
                strSid.Append(sidBytes[0].ToString());
                // Next six bytes are SID authority value.
                if (sidBytes[6] != 0 || sidBytes[5] != 0)
                {
                    string strAuth = String.Format
                        ("0x{0:2x}{1:2x}{2:2x}{3:2x}{4:2x}{5:2x}",
                        (Int16)sidBytes[1],
                        (Int16)sidBytes[2],
                        (Int16)sidBytes[3],
                        (Int16)sidBytes[4],
                        (Int16)sidBytes[5],
                        (Int16)sidBytes[6]);
                    strSid.Append("-");
                    strSid.Append(strAuth);
                }
                else
                {
                    Int64 iVal = (Int32)(sidBytes[1]) +
                        (Int32)(sidBytes[2] << 8) +
                        (Int32)(sidBytes[3] << 16) +
                        (Int32)(sidBytes[4] << 24);
                    strSid.Append("-");
                    strSid.Append(iVal.ToString());
                }

                // Get sub authority count...
                int iSubCount = Convert.ToInt32(sidBytes[7]);
                int idxAuth = 0;
                for (int i = 0; i < iSubCount; i++)
                {
                    idxAuth = 8 + i * 4;
                    UInt32 iSubAuth = BitConverter.ToUInt32(sidBytes, idxAuth);
                    strSid.Append("-");
                    strSid.Append(iSubAuth.ToString());
                }
            }
            catch (Exception ex)
            {

                return "";
            }
            return strSid.ToString();
        }

這就是您如何使用該方法並獲取 DirectoryEntry 實體的 SID。

    var coll = memberEntry.Properties;
    object obVal = coll["objectSid"].Value;
    object userSID;
    if (null != obVal)
    {
        userSID = ConvertByteToStringSid((Byte[])obVal);
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM