У меня есть SID учетной записи пользователя, и мне нужны SID групп, к которым она принадлежит.

Это должно быть получено с удаленной машины. Следующий запрос работает не для SID, а для имен групп и учетных записей.

"SELECT GroupComponent FROM Win32_GroupUser WHERE PartComponent = \"Win32_UserAccount.Domain='" + accountDomain + "',Name='" + accountName + "'\""

Возвращаемые им объекты Win32_Group представлены в виде строк и имеют только домен и имя (даже несмотря на то, что Win32_Group имеет свойство SID).

У меня такое тонущее чувство, что мне придется:

  1. Превратите SID в имя учетной записи, запросив Win32_SID;
  2. Выполните запрос выше;
  3. Превратите каждое из полученных имен групп в SID, запросив Win32_Group.

person JCCyC    schedule 22.03.2010    source источник


Ответы (2)


Можно ли использовать пространство имен System.DirectoryServices.AccountManagement классы?

using (var context = new PrincipalContext( ContextType.Domain ))
{
    using (var user = UserPrincipal.FindByIdentity( context, accountName ))
    {
        var groups = user.GetAuthorizationGroups();
        ...iterate through groups and find SIDs for each one
    }
}

Он должен работать с ContextType.Machine, хотя вам нужно будет указать имя компьютера и иметь соответствующие привилегии.

using (var context = new PrincipalContext( ContextType.Machine,
                                           "MyComputer",
                                           userid,
                                           password ))
{
   ...
}

В MSDN есть хорошая статья (хотя и длинная) об использовании нового Пространство имен управления учетными записями .NET 3.5.

person tvanfosson    schedule 22.03.2010
comment
Мне нужно иметь возможность делать это и с локальными пользователями и группами. - person JCCyC; 23.03.2010
comment
ContextType.Machine должен перечислять пользователей и группы, локальные для компьютера, указанного по имени при создании PrincipalContext. - person tvanfosson; 23.03.2010
comment
Я предполагаю, что если я подключусь к \\MACHINENAME с помощью WNetUseConnection() из mpr.dll с соответствующими удаленными учетными данными, я смогу получить информацию, даже если я и удаленная машина не являются частью одного и того же домена, верно? - person JCCyC; 23.03.2010
comment
Я считаю, что для PrincipalContext существует конструктор, который позволяет указать учетные данные (идентификатор/пароль) для использования при подключении: msdn.microsoft.com/en-us/library/bb341016.aspx - person tvanfosson; 23.03.2010
comment
Получил работу. Теперь я хочу, чтобы был метод Principal.FindBySID(). - person JCCyC; 25.03.2010
comment
Нет, подождите... есть! Principal.FindByIdentity(ctx, IdentityType.Sid, sid) - person JCCyC; 25.03.2010

Да, но некоторые методы зависят от наличия домена.

  1. См. эту страницу, чтобы узнать, как преобразовать SID в идентификатор пользователя с помощью P/ Invoke и Windows API или с .NET 2.0+ и без P/Invoke.

    используя System.Security.Principal;

    // преобразовать sid пользователя в строку домен\имя account = new SecurityIdentifier(stringSid).Translate(typeof(NTAccount)).ToString();

  2. Если у вас есть AD и идентификатор пользователя, используйте метод DirectorySearcher или API управления учетными записями для поиска групп. В противном случае используйте метод, описанный в этой статье, чтобы получить локальные группы. .

  3. Теперь используйте API, предложенный @tvanfosson, для повторения групп и получения SID. Или следуйте информации ниже.

В приложении ASP.NET можно использовать подобный код для доступа к информации о группе при условии, что пользователь прошел проверку подлинности с помощью Windows, а не проверки подлинности с помощью форм. В этом примере я оставил интересное примечание об исключениях, которые выбрасываются в этой среде, но оно может относиться и к другим пользователям:

public List<string> GetGroupsFromLogonUserIdentity()
{
    List<string> groups = new List<string>();
    HttpRequest request = HttpContext.Current.Request;

    if (request.LogonUserIdentity.Groups != null)
    {
        foreach (IdentityReference group in request.LogonUserIdentity.Groups)
        {
            try
            {
                groups.Add(group.Translate(typeof(NTAccount)).ToString());
            }
            catch (IdentityNotMappedException)
            {
                // Swallow these exceptions without throwing an error. They are
                // the result of dead objects in AD which are associated with
                // user accounts. In this application users may have a group
                // name associated with their AD profile which cannot be
                // resolved in the Active Directory.
            }
        }
    }

    return groups;
}

LogonUserIdentity основан на классе WindowsIdentity. Вы можете изменить мой пример кода, чтобы использовать WindowsIdentity и функцию в не-веб-приложении. После того, как вы переберете группу, вы сможете сделать что-то вроде этого, чтобы получить SecurityIdentifier:

SecurityIdentifier secid = group as SecurityIdentifier;
person Brian Lyttle    schedule 22.03.2010