Как я могу конвертировать из 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.Name" зависает на несколько секунд, как будто он выключается и запрашивает сеть, но затем он бросает систему.Во время выполнения.InteropServices.COMException

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

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

10 51

10 ответов:

метод Translate объекта SecurityReference работает на нелокальных идентификаторах безопасности, но только для учетных записей домена. Для учетных записей, локальных на другой машине или в недоменной настройке, вам нужно будет PInvoke функция 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();

О, тогда возможно, что вызов 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);