如何在.NET中将SID转换为字符串

29
我想将SID的System.Byte[]类型转换为字符串。
我的代码:
string path = "LDAP://DC=abc,DC=contoso,DC=com";
DirectoryEntry entry = new DirectoryEntry(path);
DirectorySearcher mySearcher = new DirectorySearcher(entry);

mySearcher.Filter = "(&(objectClass=user)(samaccountname=user1))";
results = mySearcher.FindAll();
foreach (SearchResult searchResult in results)
{
    Console.WriteLine(searchResult.Properties["ObjectSID"][0].ToString());
}

我尝试了这个方法,但它获取的值来自我当前登录的域名,而我需要获取给定域名的值。

System.Security.Principal.NTAccount(user1)
    .Translate([System.Security.Principal.SecurityIdentifier]).value
4个回答

62

看一下SecurityIdentifier类。你可以做一些简单的事情,比如,

var sidInBytes = (byte[]) *somestuff*
var sid = new SecurityIdentifier(sidInBytes, 0);
// This gives you what you want
sid.ToString();

2
在加载directoryEntry中的属性之后...
var usrId = (byte[])directoryEntry.Properties["objectSid"][0];
var objectID = (new SecurityIdentifier(usrId,0)).ToString();

1

这是我所做的,经过一些阅读后,似乎将值存储在八进制中更安全。

如果您不知道另一侧的服务器是哪个。

下面的代码显示了如何执行以获得所需结果:

private static string ExtractSinglePropertyValueFromByteArray(object value)
{
    //all if checks etc has been omitted
    string propertyValue = string.Empty;
    var bytes = (byte[])value;
    var propertyValueOct = BuildOctString(bytes); // 010500....etc
    var propertyValueSec = BuildSecString(bytes); // S-1-5-...etc
    propertyValue = propertyValueSec;
    return propertyValue;
}

private static string BuildSecString(byte[] bytes)
{
    return new SecurityIdentifier(bytes,0).Value.ToString();
}

private static string BuildOctString(byte[] bytes)
{
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < bytes.Length; i++)
    {
        sb.Append(bytes[i].ToString("X2"));
    }
    return sb.ToString();
}

0

在 .Net Core 中,SecurityIdentifier 不可用,但只要您想要字符串表示形式(也称为安全描述符定义语言或 SDDL 字符串),构造起来并不难。

基本上有一个版本号(1 字节)、一个部分计数(1 字节)、一个标识授权(6 字节)和 1 到 5 个子授权(每个 4 字节)。

我创建了一个GitHub 存储库,带有单元测试,基于一个CodeProject 文章,并添加了一个基于Miro Mannino 的 gist的转换器,将其翻译成 VB。将其翻译成 c# 留给读者作为练习...


    ''' Cribbed from https://gist.github.com/miromannino/04be6a64ea0b5f4d4254bb321e09d628
    ''' where the license was (per a comment from miro):
    ''' The License is: Do Whatever You Want With It 2.0
    ''' aka I don't care, I hope it helps you!
    Private Shared Function GetSid(byteCollection As IEnumerable(Of Byte)) As String

        ' sid[0] is the Revision, we allow only version 1, because it's the
        ' only version that exists right now.
        If byteCollection(0) <> 1 Then Throw New ArgumentOutOfRangeException("SID (bytes(0)) revision must be 1")

        Dim stringSidBuilder = New StringBuilder("S-1-")

        ' The next byte specifies the numbers of sub authorities
        ' (number of dashes minus two), should be 5 or less, but not enforcing that
        Dim subAuthorityCount = byteCollection(1)

        ' IdentifierAuthority (6 bytes starting from the second) (big endian)
        Dim identifierAuthority As Long = 0

        Dim offset = 2
        Dim size = 6
        Dim i As Integer

        For i = 0 To size - 1
            identifierAuthority = identifierAuthority Or CLng(byteCollection(offset + i)) << 8 * (size - 1 - i)
        Next

        stringSidBuilder.Append(identifierAuthority.ToString())

        ' Iterate all the SubAuthority (little-endian)
        offset = 8
        size = 4 ' 32-bits (4 bytes) for each SubAuthority
        i = 0
        While i < subAuthorityCount
            Dim subAuthority As Long = 0

            For j = 0 To size - 1
                ' the below "Or" is a logical Or not a boolean operator
                subAuthority = subAuthority Or CLng(byteCollection(offset + j)) << 8 * j
            Next
            stringSidBuilder.Append("-").Append(subAuthority)
            i += 1
            offset += size
        End While

        Return stringSidBuilder.ToString()
    End Function

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接