Лучший способ быстро определить, является ли учетная запись пользователя членом группы AD? - PullRequest
8 голосов
/ 15 декабря 2008

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

Этот код (VB.NET) пытается использовать свойство member объекта группы, но возвращает false, даже если пользователь является членом этой группы. Кто-нибудь может увидеть, что я здесь делаю не так?

Dim group As DirectoryEntry =  GetNetworkObject(GroupDomanName, NetworkObjectType.NetworkGroup, GroupName)
Dim user As DirectoryEntry =GetNetworkObject(UserDomainName, NetworkObjectType.NetworkUser, Login)

Return group.Properties("member").Contains(user.Path)

К вашему сведению: вызовы GetNetworkObject просто возвращают объект directoryEntry, я подтвердил, что правильный объект возвращается как для группы, так и для объекта пользователя.

Ответы [ 4 ]

18 голосов
/ 15 декабря 2008

Если вы используете стек .NET 3.5, Сборка System.DirectoryServices.AccountManagement.dll имеет хороший API поверх AD. Для решения вашей проблемы может быть реализован следующий метод:

static bool IsUserMemberOf(string userName, string groupName)
{
    using (var ctx = new PrincipalContext(ContextType.Domain))
    using (var groupPrincipal = GroupPrincipal.FindByIdentity(ctx, groupName))
    using (var userPrincipal = UserPrincipal.FindByIdentity(ctx, userName))
    {
        return userPrincipal.IsMemberOf(groupPrincipal);
    }
}

// Usage:
bool result = IsUserMemberOf("CONTOSO\\john.doe", "CONTOSO\\Administrators");

Я не знаю, как работает этот метод, но это чистое решение.

2 голосов
/ 15 декабря 2008

Вот что я использовал в прошлом в VBS Script, который работал очень хорошо:

Set wshNet = CreateObject("WScript.Network")                'Setup connection to the Network
Set fso = CreateObject("Scripting.FileSystemObject")        'Create File System Object for any file manipulations

Set ADSysInfo = CreateObject("ADSystemInfo")                'Setup connection to Active Directory
Set CurrentUser = GetObject("LDAP://" & ADSysInfo.UserName) 'Setup current user to look for in Active Directory
strGroups = LCase(Join(CurrentUser.MemberOf))               'Grabs all the groups the current user is a member of

Затем я использую InStr, чтобы увидеть, является ли пользователь частью этой группы:

If InStr(strGroups, "MyGroup") Then MyGroupSub

Возможно, вы сможете адаптировать вышеперечисленное в вашем проекте.

Кстати, я заметил, что в вашем коде у вас есть groupdoman в качестве вашего последнего параметра для 'group' Не уверен, хотите ли вы, чтобы это было groupdomain или нет:

Dim group As DirectoryEntry = GetNetworkObject (GroupDomanName, NetworkObjectType.NetworkGroup, GroupName, groupdoman )

против

Dim group As DirectoryEntry = GetNetworkObject (GroupDomanName, NetworkObjectType.NetworkGroup, GroupName, groupdomain )

Дайте мне знать, если это поможет! JFV

1 голос
/ 15 декабря 2008

Вот еще один способ использования поисковика каталогов и memberOf. При этом используется идентификатор объекта текущего пользователя, но вы можете изменить его на другой идентификатор.

dSearch.Filter = String.Format("(&(memberOf={0})(objectSid={1}))", groupDN, WindowsIdentity.GetCurrent.User)

Return dSearch.FindOne() IsNot Nothing

если вы собираетесь использовать пользовательский ввод, который может содержать недопустимые символы, вы всегда должны избегать их ...

searchName = searchName.Replace("\", "\5c"). _
                                Replace("/", "\2f"). _
                                Replace("*", "\2a"). _
                                Replace("(", "\28"). _
                                Replace(")", "\29")
1 голос
/ 15 декабря 2008

Я нашел ответ, который, кажется, работает в NET 2.0, относительно быстрый и устраняет возможную проблему групп, содержащих более 100 элементов (которые требуют поиска по диапазону)

Вот код, с которым я завелась:

Dim DSearcher As New DirectorySearcher(group, "(&(objectClass=user)(cn=" + Login + "))", New String() {"member;Range=0-5000"}, SearchScope.OneLevel)                  
group = GetNetworkObject(GroupDomanName, NetworkObjectType.NetworkGroup, GroupName)
user = GetNetworkObject(UserDomainName, NetworkObjectType.NetworkUser, Login)
DSearcher.AttributeScopeQuery = "member"
Return (DSearcher.FindOne() IsNot Nothing)
...