从受信任的域中将成员添加到 AD 组
Add member to AD group from a trusted domain
我有两个处于信任关系中的域,我正尝试通过 C# Web 应用程序对其进行管理。为此,我必须模拟两个不同的技术用户,但这很好用,所以我不会强调那部分代码。
要为文件系统构建正确且易于管理的 ACL,我必须
- 在域 A 中创建一个组(OK!)
- 在域 B 中查找用户(好!)
- 将用户添加到组(提交更改时失败,错误消息:
There is no such object on the server. (Exception from HRESULT: 0x80072030)
)
如果我从同一个域中添加用户,该代码可以完美运行,所以我相信我在这里只遗漏了一小部分信息。我也使用了 this document as a reference and saw 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,我被卡住了。有什么好的建议吗?
按照您的代码,我看到您将 de
作为参数获取,它位于 Domain A
中。然后您正在创建 DirectoryEntry
对象 dom
,它正在 impersonated
,但从未被使用。但是,您正在尝试使用 LDAP
直接将对象从 Domain B
添加到 de
。这一行:
de.Invoke("Add", new object[{"LDAP://domainB.company.com/CN=theUserIWantToAdd,OU=MyOU,DC=domainB,DC=company,DC=com" });
没有得到 impersonated
。
假设您的 impersonation
工作正常, 使用已经 impersonated
和 DirectorySearcher
的 dom
对象来查找用户在 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
。
最终起作用的是按照 Burzum 的建议使用委托人。您可以在问题中链接的 MSDN 文章中看到的原始代码示例在这里不起作用。因此,基于主体的方法是绝对不够的。在提交新组的更改之前,您还需要一行:
group.Properties["groupType"].Value = (-2147483644);
默认值为 0x8000000,我不得不将其更改为 0x80000004 以使其能够接受来自另一个域的 FSP。
所以现在组已经存在,它有成员,它被添加到文件夹的 ACL 中。
我有两个处于信任关系中的域,我正尝试通过 C# Web 应用程序对其进行管理。为此,我必须模拟两个不同的技术用户,但这很好用,所以我不会强调那部分代码。
要为文件系统构建正确且易于管理的 ACL,我必须
- 在域 A 中创建一个组(OK!)
- 在域 B 中查找用户(好!)
- 将用户添加到组(提交更改时失败,错误消息:
There is no such object on the server. (Exception from HRESULT: 0x80072030)
)
如果我从同一个域中添加用户,该代码可以完美运行,所以我相信我在这里只遗漏了一小部分信息。我也使用了 this document as a reference and saw 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,我被卡住了。有什么好的建议吗?
按照您的代码,我看到您将 de
作为参数获取,它位于 Domain A
中。然后您正在创建 DirectoryEntry
对象 dom
,它正在 impersonated
,但从未被使用。但是,您正在尝试使用 LDAP
直接将对象从 Domain B
添加到 de
。这一行:
de.Invoke("Add", new object[{"LDAP://domainB.company.com/CN=theUserIWantToAdd,OU=MyOU,DC=domainB,DC=company,DC=com" });
没有得到 impersonated
。
假设您的 impersonation
工作正常, 使用已经 impersonated
和 DirectorySearcher
的 dom
对象来查找用户在 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
。
最终起作用的是按照 Burzum 的建议使用委托人。您可以在问题中链接的 MSDN 文章中看到的原始代码示例在这里不起作用。因此,基于主体的方法是绝对不够的。在提交新组的更改之前,您还需要一行:
group.Properties["groupType"].Value = (-2147483644);
默认值为 0x8000000,我不得不将其更改为 0x80000004 以使其能够接受来自另一个域的 FSP。
所以现在组已经存在,它有成员,它被添加到文件夹的 ACL 中。