windows DirectoryEntry.Invoke("groups",null) 没有检索所有组?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1264028/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
DirectoryEntry.Invoke("groups",null) not retrieving all groups?
提问by HeathenWorld
I created a WCF web service to return user and group information from Active Directory. It works for most groups and users.
我创建了一个 WCF Web 服务来从 Active Directory 返回用户和组信息。它适用于大多数组和用户。
I use directoryEntry.Invoke("groups",null) to return the groups a specified user is member of. This returns MOST groups. The odd thing is I can find any group and enumerate its members, even if it is one of the groups missing when I use the invoke query on one of its members.
我使用 directoryEntry.Invoke("groups",null) 返回指定用户所属的组。这将返回 MOST 组。奇怪的是我可以找到任何组并枚举其成员,即使当我对其成员之一使用调用查询时它是丢失的组之一。
Most of the groups that exhibit this behavior are Exchange-enabled. Most of the problematic user accounts are for users in a federated domain, who use an Exchange server in the domain that I query. I am not trying to query objects in the federated domain.
大多数表现出此行为的组都启用了 Exchange。大多数有问题的用户帐户都是联合域中的用户,他们使用我查询的域中的 Exchange 服务器。我不是要查询联合域中的对象。
My theories so far:
到目前为止我的理论:
some security restriction does not allow enumerating all groups via invoke() even though I can query missing groups and enumerate their members.
invoke has issues with some subset of groups. Perhaps universal, dynamic, or Exchange-enabled properties are at play
the invoke method does not pick up all groups because the "federated" accounts (created as part of their Exchange account setup) are somehow different than regular domain accounts beyond the sid mapping back to their login domain.
某些安全限制不允许通过 invoke() 枚举所有组,即使我可以查询丢失的组并枚举其成员。
invoke 对某些组的子集有问题。也许通用的、动态的或支持 Exchange 的属性正在发挥作用
invoke 方法不会选取所有组,因为“联合”帐户(作为其 Exchange 帐户设置的一部分创建)与常规域帐户有某种不同,除了 sid 映射回其登录域之外。
回答by marc_s
There are two known issues with using the "Groups" property on a DirectoryEntry:
在 DirectoryEntry 上使用“Groups”属性有两个已知问题:
- it will not show you the "Default group" a user is in (typically "Users")
- it will not show you nested group memberships
- 它不会向您显示用户所在的“默认组”(通常是“用户”)
- 它不会显示嵌套的组成员身份
So if a user is member of a group A, and that group then in turn is member of Group B, then in Windows, this means that the user is also member of Group B. However, the DirectoryEntry will not show you that nested group membership.
因此,如果用户是 A 组的成员,而该组又是 B 组的成员,那么在 Windows 中,这意味着该用户也是 B 组的成员。但是,DirectoryEntry 不会显示该嵌套组会员资格。
Those are the two only restrictions I know of for straight Active Directory (without Exchange).
这是我所知道的对直接 Active Directory(没有 Exchange)仅有的两个限制。
Getting the default group is a bit involved, but I do have a code sample for that.
获取默认组有点复杂,但我确实有一个代码示例。
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();
}
Getting the nested groups also takes a few steps and I'll have to hunt for a solution to that one, if that's the problem.
获取嵌套组也需要几个步骤,如果这是问题所在,我将不得不寻找解决方案。
Marc
马克
PS: as a side note - why on earth are you doing a "DirectoryEntry.Invoke("groups", null)" call? Why don't you just enumerate the DirectoryEntry.Properties["memberOf"] property which is multi-valued (contains multiple values) and has the group's DN (distinguished name) in it?
PS:作为旁注 - 你到底为什么要进行“DirectoryEntry.Invoke(“groups”,null)”调用?为什么不枚举 DirectoryEntry.Properties["memberOf"] 属性,该属性是多值的(包含多个值)并且其中包含组的 DN(专有名称)?
foreach(string groupDN in myUser.Properties["memberOf"])
{
string groupName = groupDN;
}
OR if you're on .NET 3.5, you can make use of the new Security Principal classes in S.DS.AccountManagement. One of them is a "UserPrincipal", which has a method called "GetAuthorizationGroups()" which does all this hard work for you - for free, basically!
或者,如果您使用的是 .NET 3.5,则可以使用 S.DS.AccountManagement 中的新安全主体类。其中之一是“UserPrincipal”,它有一个名为“GetAuthorizationGroups()”的方法,它为您完成所有这些艰苦的工作——基本上是免费的!
See an excellent MSDN articlethat describes these new .NET 3.5 S.DS features for you.
回答by On Freund
I think marc_s is correct. If you want all groups, you can use the following snippet:
我认为 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;
}
Note that calculating nested groups is an expensive operation, so RefreshCache might take a long time to complete.
请注意,计算嵌套组是一项开销很大的操作,因此 RefreshCache 可能需要很长时间才能完成。
回答by On Freund
On Freund,
关于弗洛因德,
I am trying to make use of your code and not getting very far. I have updated the directory entry path to be "LDAP://DC=myDomain,DC=co,DC=uk" but I am not getting any results (obj.Properties["tokenGroups"].Count = 0)
我正在尝试使用您的代码并且不会走得太远。我已将目录条目路径更新为“LDAP://DC=myDomain,DC=co,DC=uk”,但没有得到任何结果 (obj.Properties["tokenGroups"].Count = 0)
I don't udnerstand how the user to list group for is specified.
我不明白如何指定要为其列出组的用户。
Could you please point me in the right direction?
你能指出我正确的方向吗?
Thanks
谢谢
EDIT:
编辑:
I got it sorted in the end. The directory entry to get the token groups from should be a user entry... if that makes sense...
我最后整理好了。从中获取令牌组的目录条目应该是用户条目……如果有意义的话……
I've included some code in case anyone else has the same query:
我已经包含了一些代码,以防其他人有相同的查询:
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