IAm*_*rey 31 .net c# active-directory
我希望得到一个用户在Active Directory中成为其成员的所有组的列表,这两个组都明确列在memberOf属性列表中,也隐式通过嵌套组成员身份列出.例如,如果我检查UserA并且UserA是GroupA和GroupB的一部分,我还想列出GroupC,如果GroupB是GroupC的成员.
为了让您更深入地了解我的应用程序,我将在有限的基础上进行此操作.基本上,我偶尔会想要进行安全检查,以便列出这些额外的会员资格.我想区分这两者,但这应该不难.
我的问题是我没有找到一种有效的方法来使这个查询工作.Active Directory上的标准文本(此CodeProject文章)显示了一种基本上是递归查找的方法.这似乎非常低效.即使在我的小域中,用户也可能拥有30多个组成员资格.这意味着为一个用户调用30多个Active Directory.
我查看了以下LDAP代码,以便一次获取所有memberOf条目:
(memberOf:1.2.840.113556.1.4.1941:={0})
Run Code Online (Sandbox Code Playgroud)
其中{0}将是我的LDAP路径(例如:CN = UserA,OU = Users,DC = foo,DC = org).但是,它不会返回任何记录.这种方法的缺点,即使它起作用,也就是我不知道哪个组是明确的,哪个是隐含的.
这就是我到目前为止所拥有的.我想知道是否有比CodeProject文章更好的方法,如果有的话,如何实现(实际代码将是美好的).我使用的是.NET 4.0和C#.我的Active Directory处于Windows 2008功能级别(它还不是R2).
JPB*_*anc 24
渴望这是一个有趣的问题.
接下来,只是一个修正,你说:
我查看了以下LDAP代码,以便一次获取所有memberOf条目:
(memberOf:1.2.840.113556.1.4.1941:={0})
Run Code Online (Sandbox Code Playgroud)
你不能让它发挥作用.我记得当我了解它的存在时它让它工作,但它在LDIFDE.EXE过滤器中.所以我将它应用于C#中的ADSI,它仍在工作.我从Microsoft获取的示例中有太多括号,但它正在工作(源代码在AD搜索过滤器语法中).
根据您关于我们不知道用户是否明确属于该组这一事实的说法,我再添加一个请求.我知道这不是很好,但这是最好的我能做到的.
static void Main(string[] args)
{
/* Connection to Active Directory
*/
DirectoryEntry deBase = new DirectoryEntry("LDAP://WM2008R2ENT:389/dc=dom,dc=fr");
/* To find all the groups that "user1" is a member of :
* Set the base to the groups container DN; for example root DN (dc=dom,dc=fr)
* Set the scope to subtree
* Use the following filter :
* (member:1.2.840.113556.1.4.1941:=cn=user1,cn=users,DC=x)
*/
DirectorySearcher dsLookFor = new DirectorySearcher(deBase);
dsLookFor.Filter = "(member:1.2.840.113556.1.4.1941:=CN=user1 Users,OU=MonOu,DC=dom,DC=fr)";
dsLookFor.SearchScope = SearchScope.Subtree;
dsLookFor.PropertiesToLoad.Add("cn");
SearchResultCollection srcGroups = dsLookFor.FindAll();
/* Just to know if user is explicitly in group
*/
foreach (SearchResult srcGroup in srcGroups)
{
Console.WriteLine("{0}", srcGroup.Path);
foreach (string property in srcGroup.Properties.PropertyNames)
{
Console.WriteLine("\t{0} : {1} ", property, srcGroup.Properties[property][0]);
}
DirectoryEntry aGroup = new DirectoryEntry(srcGroup.Path);
DirectorySearcher dsLookForAMermber = new DirectorySearcher(aGroup);
dsLookForAMermber.Filter = "(member=CN=user1 Users,OU=MonOu,DC=dom,DC=fr)";
dsLookForAMermber.SearchScope = SearchScope.Base;
dsLookForAMermber.PropertiesToLoad.Add("cn");
SearchResultCollection memberInGroup = dsLookForAMermber.FindAll();
Console.WriteLine("Find the user {0}", memberInGroup.Count);
}
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
在我的测试树中,这给出:
LDAP://WM2008R2ENT:389/CN=MonGrpSec,OU=MonOu,DC=dom,DC=fr
adspath : LDAP://WM2008R2ENT:389/CN=MonGrpSec,OU=MonOu,DC=dom,DC=fr
cn : MonGrpSec
Find the user 1
LDAP://WM2008R2ENT:389/CN=MonGrpDis,OU=ForUser1,DC=dom,DC=fr
adspath : LDAP://WM2008R2ENT:389/CN=MonGrpDis,OU=ForUser1,DC=dom,DC=fr
cn : MonGrpDis
Find the user 1
LDAP://WM2008R2ENT:389/CN=MonGrpPlusSec,OU=ForUser1,DC=dom,DC=fr
adspath : LDAP://WM2008R2ENT:389/CN=MonGrpPlusSec,OU=ForUser1,DC=dom,DC=fr
cn : MonGrpPlusSec
Find the user 0
LDAP://WM2008R2ENT:389/CN=MonGrpPlusSecUniv,OU=ForUser1,DC=dom,DC=fr
adspath : LDAP://WM2008R2ENT:389/CN=MonGrpPlusSecUniv,OU=ForUser1,DC=dom,DC=fr
cn : MonGrpPlusSecUniv
Find the user 0
Run Code Online (Sandbox Code Playgroud)
(编辑)'1.2.840.113556.1.4.1941'在W2K3 SP1中不起作用,它开始与SP2一起使用.我认为它与W2K3 R2相同.它应该适用于W2K8.我在这里用W2K8R2测试.我很快就能在W2K8上测试一下.
如果除了递归调用之外没有办法(我不相信),那么至少你可以让框架为你工作:参见UserPrincipal.GetAuthorizationGroups方法(在System.DirectoryServices.AccountManagement命名空间中并在.Net 3.5中引入)
此方法以递归方式搜索所有组,并返回用户所属的组.返回的集合还可以包括系统将用户视为授权目的的其他组.
与GetGroups 的结果("返回指定当前主体是其成员的组的组对象的集合")进行比较,以查看成员资格是显式还是隐式.