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

发布于 2024-12-09 09:02:40 字数 639 浏览 0 评论 0原文

我被指派修改 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);

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

我考虑过使用硬编码的 SID 字符串,但我不知道这有多“正确”。

I've been assigned to modify a WinForms application to basically check that the logged on user belongs to a specific domain.
This is what I've come up with so far:

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);

Is there a better/easier way to do this?
To me it seems like the domainSid would be accessible in some way using the PrincipalContext or some other class in System.Security.Principal.

I've considered using a hardcoded SID-string, but I don't know how "correct" that would be.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

甜是你 2024-12-16 09:02:40

你正在做的事情对我来说似乎是最好的选择。对字符串进行硬编码绝对不是一个好主意。

What you're doing looks like the best option to me. Hardcoding strings is definetely not a good idea.

謌踐踏愛綪 2024-12-16 09:02:40

每个域都有一个内置帐户 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 实现相同的结果。这对我来说似乎是最优雅的方式。

Each domain has a build in account domainName\administrator, so you can create an account with this name, translate it to the SecurityIdentifier and read the AccountDomainSid property.

An example of this way is:

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;
    }
}

Also you can find other solutions to achieve the same result via WMI or Lsa. This one seems the most elegant way for me.

野稚 2024-12-16 09:02:40

这是与已接受答案略有不同的方法:

C#

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# One Liner

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)

Here's a slightly different approach to the accepted answer:

C#

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# One Liner

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)
聊慰 2024-12-16 09:02:40

要获取域的 sid,只需要这个简单的查询:

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 的权限时,此方法会引发异常。

To get the sid of domain just this simple query is needed:

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

Caution: this method throws exceptions when the domain name cannot be resolved or the user has no permissions to query Active Directory.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文