![](/img/trans.png)
[英]When does WinNT:// provider query Active Directory? Or how to get SID of local group member if it is domain account
[英]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));
这是如何运作的
PrincipalContext
定义在何处查找第一组,在本例中为“本地机器”。PrincipalContext
。 如果该组属于域,它将使用域上下文自动查找,如果它是本地机器组,它将使用本地机器。要获得 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.