2008-12-15 21 views
8

我目前有一些代碼可以拉下組中的用戶列表,然後遍歷該組來確定給定的帳戶是否存在,但似乎應該有一個更簡潔(也許更快)的方式來完成這個。快速確定用戶帳戶是否爲AD組的成員的最佳方法?

此代碼(VB.NET)嘗試使用組對象的成員屬性,但即使用戶是該組的成員,它也返回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) 

FYI:本GetNetworkObject調用只返回一個DirectoryEntry對象,我已經證實了正確的對象被返回兩個組和用戶對象。

回答

18

如果你在.NET 3.5棧上,System.DirectoryServices.AccountManagement.dll assembly在AD上面有一個很好的API。可以實施下面的方法來解決您的問題:

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"); 

我不知道這種方法是如何執行,但它是一種清潔的解決方案。

+1

感謝。我甚至沒有意識到3.5爲AD添加了(非常需要的)抽象層。我會給你一個答案的投票,因爲它很好,但是我的部署環境仍然是NET 2.0。 – JohnFx 2008-12-15 16:28:27

2

以下是我在一個VBS腳本過去那種工作非常出色用過:

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爲「集團」不知道你的最後一個參數,如果你想,要成爲groupdomain與否:

暗淡組作爲的DirectoryEntry = GetNetworkObject(GroupDomanName,NetworkObjectType.NetworkGroup,組名,groupdoman

VS

昏暗組作爲的DirectoryEntry = GetNetworkObject(GroupDomanName,NetworkObjectType.NetworkGroup,組名,groupdomain

讓我知道,如果這有助於! JFV

+0

有很好的關於groupdomain參數的信息。實際上,這是一些代碼的一部分,與我只刪除了一半的問題無關(oops,現在已修復),它允許我通過組織的OU。 – JohnFx 2008-12-15 16:49:53

1

我發現,似乎在.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) 
+1

擡頭。當我完成測試後,我會調整此條目,但是我發現它在兩種情況下失敗: 1)如果用戶存在於組中,但來自另一個受信任的林。 2)如果具有相同名稱但不同域名的用戶是該組的成員。 – JohnFx 2008-12-16 05:14:54

+0

這個工作是否也是遞歸的?我不認爲會。 – benPearce 2008-12-29 02:56:25

1

這是另一種使用目錄搜索器和memberOf的方法。這是使用當前用戶的objectSID,但你可以將其改爲其他標識符。

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") 
相關問題