从受信任的域添加成员到AD组

时间:2015-08-13 09:15:22

标签: c# active-directory active-directory-group

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

要为文件系统构建正确且易于管理的ACL,我必须

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

如果我在同一个域中添加用户,代码就能完美运行,所以我相信我在这里只缺少一小部分信息。我使用了this document作为参考,并且也看到了this question(还有一些引用了此错误消息),但它们都没有帮助。

代码(删除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,我就陷入了困境。有什么好建议吗?

2 个答案:

答案 0 :(得分:5)

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

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

未获得impersonated

假设您的impersonation工作正常,请使用已dom impersonated DirectorySearcher的{​​{1}}对象在Domain B中找到该用户然后将用户对象从Domain B添加到de

...
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("<SID={0}>", userPrincipal.SID.ToString());
                DirectoryEntry groupDirectoryEntry = (DirectoryEntry)groupPrincipal.GetUnderlyingObject();
                groupDirectoryEntry.Properties["member"].Add(userSid);
                groupDirectoryEntry.CommitChanges();
              }
           }
        }
     }
 }

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

答案 1 :(得分:0)

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

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

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

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