2009-08-12 23 views
4

我創建了一個WCF Web服務來從Active Directory返回用戶和組信息。它適用於大多數組和用戶。DirectoryEntry.Invoke(「groups」,null)不檢索所有組?

我使用directoryEntry.Invoke(「groups」,null)返回指定用戶所屬的組。這將返回MOST組。奇怪的是,我可以找到任何組並枚舉它的成員,即使它是我在其中一個成員上使用調用查詢時缺少的組之一。

顯示此行爲的大多數組都啓用了Exchange。大多數有問題的用戶帳戶都是在聯合域中的用戶,他們在我查詢的域中使用Exchange服務器。我沒有試圖查詢聯合域中的對象。

我的理論迄今:

  • 一些安全限制不允許通過調用枚舉所有組(),即使我可以查詢失蹤組和枚舉它們的成員。

  • 調用對某些子組的子集有問題。可能是通用的,動態的或支持Exchange的屬性

  • 由於「聯合」帳戶(作爲其Exchange帳戶設置的一部分創建)在某種程度上與普通域帳戶不同,因此invoke方法不會拾取所有組超出了sid映射回他們的登錄域。

回答

5

有使用上一個DirectoryEntry的「組」屬性的兩個已知問題:

  • 它不會告訴你「默認組」用戶是在(通常爲「用戶」)
  • 它不會告訴你嵌套組成員

因此,如果用戶是A組的成員,該組隨後又是B組的成員,然後在Windows中,這意味着用戶還成員 B組。但是,DirectoryEntry不會向您顯示嵌套的組成員資格。

這些是我知道的直接Active Directory(無Exchange)的兩個限制。

獲取默認組有點涉及,但我確實有一個代碼示例。

private string GetPrimaryGroup(DirectoryEntry aEntry, DirectoryEntry aDomainEntry) 
{ 
    int primaryGroupID = (int)aEntry.Properties["primaryGroupID"].Value; 
    byte[] objectSid = (byte[])aEntry.Properties["objectSid"].Value; 

    StringBuilder escapedGroupSid = new StringBuilder(); 

    // Copy over everything but the last four bytes(sub-authority) 
    // Doing so gives us the RID of the domain 
    for(uint i = 0; i < objectSid.Length - 4; i++) 
    { 
     escapedGroupSid.AppendFormat("\\{0:x2}", objectSid[i]); 
    } 

    //Add the primaryGroupID to the escape string to build the SID of the primaryGroup 
    for(uint i = 0; i < 4; i++) 
    { 
     escapedGroupSid.AppendFormat("\\{0:x2}", (primaryGroupID & 0xFF)); 
     primaryGroupID >>= 8; 
    } 

    //Search the directory for a group with this SID 
    DirectorySearcher searcher = new DirectorySearcher(); 
    if(aDomainEntry != null) 
    { 
     searcher.SearchRoot = aDomainEntry; 
    } 

    searcher.Filter = "(&(objectCategory=Group)(objectSID=" + escapedGroupSid.ToString() + "))"; 
    searcher.PropertiesToLoad.Add("distinguishedName"); 

    return searcher.FindOne().Properties["distinguishedName"][0].ToString(); 
} 

獲取嵌套組還需要幾個步驟,我將不得不尋找一個解決一個,如果是這樣的問題。

馬克

PS:作爲一個方面說明 - 爲什麼地球上,你做一個 「DirectoryEntry.Invoke(」 組 「NULL)」 的口號?爲什麼不只是枚舉多值(包含多個值)並具有組的DN(可分辨名稱)的DirectoryEntry.Properties [「memberOf」]屬性?

foreach(string groupDN in myUser.Properties["memberOf"]) 
{ 
    string groupName = groupDN; 
} 

或者如果您使用的是.NET 3.5,則可以使用S.DS.AccountManagement中的新安全主體類。其中一個是「UserPrincipal」,它有一個名爲「GetAuthorizationGroups()」的方法,它可以免費爲您完成所有這些工作 - 基本上是這樣!

看到一個很好的MSDN article,它描述了這些新的.NET 3.5 S.DS功能。

+0

這些是很好的建議,你對MSDN文章是正確的,我應該在開始之前閱讀它。關於爲什麼我使用invoke方法,在這種情況下,我所需要的只是組名,而這看起來像是一種獲取信息的有效方式。我沒有對Active Directory進行過多的編程,所以我仍然非常瞭解繼續進行的最佳方式。從1.1開始,這個領域已經發展了多少.NET是很有趣的! – HeathenWorld 2009-08-13 01:30:43

+0

完全沒有問題 - 只是好奇你是否有使用Invoke()方法的特殊原因。嘿 - 這就是StackOverflow的全部內容 - 當你沒有看到樹木的森林時幫助你:-) – 2009-08-13 05:17:35

+0

對於鏈接的MSDN文章+1,在3.5中更容易 – tbone 2009-09-28 19:38:43

0

我認爲marc_s是正確的。如果你想所有組,可以使用下面的代碼片段:

using (DirectoryEntry obj = new DirectoryEntry("LDAP://" + dn)) 
{ 
    obj.RefreshCache(new string[] { "tokenGroups" }); 
    string[] sids = new string[obj.Properties["tokenGroups"].Count]; 
    int i = 0; 
    foreach (byte[] bytes in obj.Properties["tokenGroups"]) 
    { 
     sids[i] = _ConvertSidToString(bytes); 
     ++i; 
    } 
    obj.Close(); 
    return sids; 
} 

注意計算嵌套組是昂貴的操作,所以RefreshCache可能需要很長的時間才能完成。

0

在弗氏,

我想利用你的代碼,並沒有得到很遠。我已更新目錄條目路徑爲「LDAP:// DC = myDomain,DC = co,DC = uk」但我沒有收到任何結果(obj.Properties [「tokenGroups」]。Count = 0)

我不udnerstand如何指定用戶列表組。

請你指點我正確的方向?

感謝

編輯:

我明白了到底排序。目錄項獲得令牌組從應該是一個用戶條目......如果是有道理的......

我已經包括萬一別人的一些代碼有相同的查詢:

Dim directoryEntry As DirectoryEntry = _ 
     New DirectoryEntry("LDAP://CN=users,DC=domanName,DC=com") 
Dim directorySearcher As DirectorySearcher = _ 
     New DirectorySearcher(directoryEntry, "(sAMAccountName=" & UserName & ")") 
Dim searchResult As SearchResult = directorySearcher.FindOne() 

If Not searchResult Is Nothing Then 
    Dim userDirectoryEntry As DirectoryEntry = searchResult.GetDirectoryEntry 
    userDirectoryEntry.RefreshCache(New String() {"tokenGroups"}) 
    ... etc ... 
End If