Как я могу конвертировать из SID в имя учетной записи в C#

у меня есть приложение c#, которое сканирует каталог и собирает какую-то информацию. Я хотел бы отобразить имя учетной записи для каждого файла. Я могу сделать это в локальной системе, получив SID для объекта FileInfo, а затем выполнив:

string GetNameFromSID( SecurityIdentifier sid )
{
    NTAccount ntAccount = (NTAccount)sid.Translate( typeof( NTAccount ) );
    return ntAccount.ToString();
}

однако это не работает для файлов в сети, предположительно потому, что функция Translate () работает только с локальными учетными записями пользователей. Я подумал, что, возможно, я мог бы сделать поиск LDAP на SID, поэтому я попробовал следующий:

string GetNameFromSID( SecurityIdentifier sid )
{
    string str = "LDAP://<SID=" + sid.Value + ">";
    DirectoryEntry dirEntry = new DirectoryEntry( str );
    return dirEntry.Name;
}

похоже, что это сработает, в том, что доступ к " dirEntry.Имя " зависает на несколько секунд, как будто он отключается и запрашивает сеть, но затем он бросает систему.Во время выполнения.InteropServices.Исключение comexception

кто-нибудь знает как я могу получить имя учетной записи произвольного файла или Сид? Я не знаю много о сети или LDAP или что-то еще. Есть класс DirectorySearcher, который, возможно, я должен использовать, но ему нужно доменное имя, и я не знаю, как это получить - все, что у меня есть, это путь к каталогу, который я сканирую.

спасибо заранее.

10 ответов


метод Translate объекта SecurityReference работает на нелокальных SIDs, но только для учетных записей домена. Для учетных записей, локальных на другой машине или в недоменной установке, вам нужно будет вызвать функцию LookupAccountSid, указав конкретное имя машины, на которой необходимо выполнить поиск.


смотрите здесь для хорошего ответа:

лучший способ разрешить отображение имени пользователя по SID?

суть этого бит:

string sid="S-1-5-21-789336058-507921405-854245398-9938";
string account = new System.Security.Principal.SecurityIdentifier(sid).Translate(typeof(System.Security.Principal.NTAccount)).ToString();

этот подход работает для меня для нелокальных SID над active directory.



в C# получите SID пользователя и назначьте его строковой переменной через:

string strUser = System.Security.Principal.WindowsIdentity.GetCurrent().User.ToString();

вам нужно будет использовать строку, потому что возможность разрешить имя пользователя поддерживает строку. Другими словами, использование VAR varUser приведет к ошибке пространства имен.

string strUserName = new System.Security.Principal.SecurityIdentifier(strUser).Translate(typeof(System.Security.Principal.NTAccount)).ToString();

Ooh, тогда возможно, что вызов LDAP не работает, потому что вы не можете быть в среде Active Directory. Если это так, то каждая из ваших машин отвечает за свое собственное хранилище удостоверений. И ваш первый образец кода не работает по сети, потому что машина, на которой вы выполняете свой код, не знает, как разрешить SID, который имеет смысл только на удаленной машине.

вы действительно должны проверить, являются ли ваши машины частью служба Active Directory. Вы бы знали это во время процесса входа в систему. Или вы можете проверить, щелкнув правой кнопкой мыши на "мой компьютер", выберите" Свойства", вкладку" имя компьютера", а затем посмотреть, является ли ваш компьютер частью домена.


большой. Я списал код LookupAccountSid () отсюда:

http://www.pinvoke.net/default.aspx/advapi32.LookupAccountSid

и это сработало, хотя я должен был сам предоставить имя хоста. В случае пути UNC я могу просто взять первый компонент. Когда это сопоставленный диск, я использую этот код для преобразования пути в UNC:

http://www.wiredprairie.us/blog/index.php/archives/22

Это кажется, работает, так что я сделаю это, если кто-то не придумает ситуацию, в которой первый компонент пути UNC не является именем хоста...

спасибо всем за помощь.


вы также можете получить имя учетной записи специальных учетных записей, таких как" все " с таким кодом, который будет работать независимо от языковых настроек пользователя:

   SecurityIdentifier everyoneSid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
   string everyone = everyoneSid.Translate(typeof(System.Security.Principal.NTAccount)).ToString();

этот-тупик. Вы находитесь в среде Active Directory, правильно? Просто проверка:)

во всяком случае, вместо привязки с sid.Значения

string str = "LDAP://<SID=" + sid.Value + ">";

Я бы попытался преобразовать массив байтов SID в Октетная Строка и привязать его.

есть сладкий пример здесь на стр. 78. Это приблизит тебя. Честно говоря, я раньше не пробовал связываться с Сидом. Но у меня был успех в связывании с GUID пользователя, хотя:)

удачи и дайте мне знать, как она идет.


получить текущий домен:

System.DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain();

получить запись каталога из ldap и доменное имя:

DirectoryEntry de = new DirectoryEntry(string.Format("LDAP://{0}", domain));

получить sid от ActiveDirectoryMembershipProvider ActiveDirectoryMembershipUser:

ActiveDirectoryMembershipUser user = (ActiveDirectoryMembershipUser)Membership.GetUser();
var sid = (SecurityIdentifier)user.ProviderUserKey;

получить имя пользователя от SecurityIdentifier:

(NTAccount)sid.Translate(typeof(NTAccount));

получить поиск каталога сделано на activedirectory с записью каталога домена и имя пользователя:

DirectorySearcher search = new DirectorySearcher(entry);
        search.Filter = string.Format("(SAMAccountName={0})", username);
        search.PropertiesToLoad.Add("Name");
        search.PropertiesToLoad.Add("displayName");
        search.PropertiesToLoad.Add("company");
        search.PropertiesToLoad.Add("homePhone");
        search.PropertiesToLoad.Add("mail");
        search.PropertiesToLoad.Add("givenName");
        search.PropertiesToLoad.Add("lastLogon");
        search.PropertiesToLoad.Add("userPrincipalName");
        search.PropertiesToLoad.Add("st");
        search.PropertiesToLoad.Add("sn");
        search.PropertiesToLoad.Add("telephoneNumber");
        search.PropertiesToLoad.Add("postalCode");
        SearchResult result = search.FindOne();
        if (result != null)
        {
            foreach (string key in result.Properties.PropertyNames)
            {
                // Each property contains a collection of its own
                // that may contain multiple values
                foreach (Object propValue in result.Properties[key])
                {
                    outputString += key + " = " + propValue + ".<br/>";
                }
            }
        }

в зависимости от данных в active directory, вы получите разнообразный ответ на выходе.

вот сайт, который имеет все свойства пользователя, которые мне нужны:


Я совершенно уверен, что вы сможете использовать принятый ответ здесь: определите имя учетной записи LocalSystem с помощью C#

в принципе, вы можете перевести экземпляр класса SecurityIdentifier в тип NTAccount, из которого вы можете получить имя пользователя. В коде:

using System.Security.Principal;

SecurityIdentifier sid = new SecurityIdentifier("S-1-5-18");
NTAccount acct = (NTAccount)sid.Translate(typeof(NTAccount));
Console.WriteLine(acct.Value);