从可信域添加成员到AD组

我有两个域,在一个受信任的关系中,我正在尝试从C#Web应用程序进行管理。 要做到这一点,我必须冒充两个不同的技术用户,但这样做很好,所以我不会强调代码的那一部分。

为了构建适当且易于管理的文件系统ACL,我必须这样做

  • 在domainA中创建一个组(OK!)
  • 在domainB中找到一个用户(好的!)
  • 将用户添加到组(提交更改时失败,错误消息: There is no such object on the server. (Exception from HRESULT: 0x80072030)

如果我正在添加来自同一域的用户,则代码可以正常运行,所以我相信我在这里只缺少一些小的部分信息。 我使用这个文档作为参考,也看到了这个问题 (还有一些引用了这个错误信息),但他们都没有帮助。

代码(删除了try-catch块以使其更简单)

 // de is a DirectoryEntry object of the AD group, received by the method as a parameter // first impersonation to search in domainB // works all right if (impersonator.impersonateUser("techUser1", "domainB", "pass")) { DirectoryEntry dom = new DirectoryEntry("LDAP://domainB.company.com/OU=MyOU,DC=domainB,DC=company,DC=com", "techUser1", "pass"); de.Invoke("Add", new object[] { "LDAP://domainB.company.com/CN=theUserIWantToAdd,OU=MyOU,DC=domainB,DC=company,DC=com" }); // de.Invoke("Add", new object[] { "LDAP://domainA.company.com/CN=anotherUserFromDomainA,OU=AnotherOU,DC=domainB,DC=company,DC=com" }); impersonator.undoImpersonation(); } // second impersonation because the group (de) is in domainA // and techUser2 has account operator privileges there if (impersonator.impersonateUser("techUser2", "domainA", "pass")) { de.CommitChanges(); impersonator.undoImpersonation(); return true; } else { // second impersonation was unsuccessful, so return an empty object return false; } 

第6行工作,如果我调试它或强制将属性写入HttpResponse,它显然在那里。 所以LDAP查询似乎没问题。

另外,如果我注释掉第6行并取消注释7,那么基本上我从同一个域添加一个用户, 整个过程奇迹般地工作 。 有了domainB,我就被困住了。 有什么好建议吗?

按照你的代码,我看到你将de作为参数,在Domain A 。 然后你正在创建DirectoryEntry对象dom ,它被impersonated ,但从未被使用过。 但是,您尝试直接使用LDAPDomain B的对象添加到de 。 这一行:

 de.Invoke("Add", new object[{"LDAP://domainB.company.com/CN=theUserIWantToAdd,OU=MyOU,DC=domainB,DC=company,DC=com" }); 

没有被impersonated

假设您的impersonation正常工作,请使用已使用DirectorySearcher impersonated dom对象在Domain B查找用户,然后将用户对象从Domain Bde

 ... using (DirectoryEntry dom = new DirectoryEntry("LDAP://domainB.company.com/OU=MyOU,DC=domainB,DC=company,DC=com", "techUser1", "pass")) { using (DirectorySearcher searcher = new DirectorySearcher(dom)) { searcher.Filter = "(&(objectClass=user)(CN=theUserIWantToAdd))"; SearchResult result = searcher.FindOne(); de.Invoke("Add", new object[] { result.Path }); } } ... 

UDPATE

此示例将向您展示如何从一个域获取用户SID ,从另一个域获取搜索组以及如何使用SID将用户添加到组。

 //GET THE USER FROM DOMAIN B using (UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(domainContext, UPN)) { if (userPrincipal != null) { //FIND THE GROUP IN DOMAIN A using (GroupPrincipal groupPrincipal = GroupPrincipal.FindByIdentity(domainContext, groupName)) { if (groupPrincipal != null) { //CHECK TO MAKE SURE USER IS NOT IN THAT GROUP if (!userPrincipal.IsMemberOf(groupPrincipal)) { string userSid = string.Format("", userPrincipal.SID.ToString()); DirectoryEntry groupDirectoryEntry = (DirectoryEntry)groupPrincipal.GetUnderlyingObject(); groupDirectoryEntry.Properties["member"].Add(userSid); groupDirectoryEntry.CommitChanges(); } } } } } 

请注意,我跳过了上述代码中的所有impersonation

最终有效的是使用校长,如Burzum所建议的那样。 您可以在问题中链接的MSDN文章中看到的原始代码示例在此处不起作用。 因此,基于Principal的方法是必须坚持不够的。 在提交新组的更改之前,您还需要一行:

 group.Properties["groupType"].Value = (-2147483644); 

默认值为0x8000000,我不得不将其更改为0x80000004,以使其能够接受来自其他域的FSP。

所以现在该组存在,它有成员,它被添加到文件夹的ACL中。