是否有更好(更简单)的方法来获取特定域的SID ?

本文关键字:获取 SID 方法 更好 更简单 是否 | 更新日期: 2023-09-27 18:11:01

我被分配修改一个WinForms应用程序,基本上检查登录的用户属于一个特定的域。这是我目前想到的:

byte[] domainSid;
var directoryContext =
    new DirectoryContext(DirectoryContextType.Domain, "domain.se");
using (var domain = Domain.GetDomain(directoryContext))
using (var directoryEntry = domain.GetDirectoryEntry())
    domainSid = (byte[])directoryEntry.Properties["objectSid"].Value;
var sid = new SecurityIdentifier(domainSid, 0);
bool validUser = UserPrincipal.Current.Sid.IsEqualDomainSid(sid);

有更好/更简单的方法来做这件事吗?对我来说,domainSid似乎可以通过使用PrincipalContext或System.Security.Principal中的其他类以某种方式访问。

我考虑过使用硬编码的SID-string,但我不知道这有多"正确"。

是否有更好(更简单)的方法来获取特定域的SID ?

你所做的对我来说是最好的选择。硬编码字符串绝对不是一个好主意。

每个域都有一个内置帐户domainName'administrator,因此您可以使用此名称创建一个帐户,将其转换为SecurityIdentifier并读取AccountDomainSid属性。

public static class SecurityEx
{
    public static SecurityIdentifier DomainSId
    {
        get
        {               
            var administratorAcount = new NTAccount(GetDomainName(), "administrator");
            var administratorSId = (SecurityIdentifier) administratorAcount.Translate(typeof (SecurityIdentifier));
            return administratorSId.AccountDomainSid;
        }
    }
    internal static string GetDomainName()
    {
        //could be other way to get the domain name through Environment.UserDomainName etc...
        return IPGlobalProperties.GetIPGlobalProperties().DomainName;
    }
}

也可以通过WMI或Lsa找到其他解决方案来实现相同的结果。

对于接受的答案,这里有一个稍微不同的方法:

c # 35;

using System.Security.Principal; 
using System.DirectoryServices;  
//...
void Main()
{
    var sidHelp = new SecurityIdentifierHelper();
    Console.WriteLine(sidHelp.GetDomainSecurityIdentifier("MyDomain"));
}
//...
public class SecurityIdentifierHelper
{
    const int OffsetBinaryFormStartingIndex = 0; // just to avoid magic numbers; though this is still a bit magic.  Documentation says "The byte offset to use as the starting index in binaryForm", whatever that means.
                                                 // https://referencesource.microsoft.com/#mscorlib/system/security/principal/sid.cs,d06a8d5ee0c7a26d,references
                                                 // https://learn.microsoft.com/en-us/dotnet/api/system.security.principal.securityidentifier.-ctor?view=netframework-4.8#System_Security_Principal_SecurityIdentifier__ctor_System_Byte___System_Int32_
    public SecurityIdentifier GetDomainSecurityIdentifier(string domain)
    {
        var ldapPath = $"LDAP://{domain}";
        var domainAdsi = new DirectoryEntry(ldapPath);
        var domainSidByteArray = (byte[])domainAdsi.Properties["objectSid"].Value;
        return new SecurityIdentifier(domainSidByteArray, OffsetBinaryFormStartingIndex);
    }
}

c # 35;一个班轮

Console.WriteLine(new System.Security.Principal.SecurityIdentifier(((byte[])new System.DirectoryServices.DirectoryEntry("LDAP://MyDomain").Properties["objectSid"].Value), 0));

PowerShell:

[string]$myDomain = 'MyDomain' # or 'MyDomain.example.com'
[string]$ldapPath = 'LDAP://{0}' -f $MyDomain
[adsi]$domainAdsi = [adsi]$ldapPath
[System.Security.Principal.SecurityIdentifier]::new($domainAdsi.Value, 0)

PowerShell 1 Liner:

[System.Security.Principal.SecurityIdentifier]::new(([ADSI]('LDAP://MyDomain')).Value, 0)

要获得域名的名称,只需要这个简单的查询:

public static SecurityIdentifier GetDomainSid(string domainName)
{
    byte[] domainSidBytes = ((byte[])new System.DirectoryServices.DirectoryEntry($"LDAP://{ domainName }").Properties["objectSid"].Value);
    SecurityIdentifier sid = new System.Security.Principal.SecurityIdentifier(domainSidBytes, 0);
    return sid;
}

注意:当域名无法解析或用户没有查询Active Directory的权限时,此方法将抛出异常。