我正在尝试使用以下代码段创建新用户。
using (var ad =
new PrincipalContext(ContextType.Domain,
"<domain>",
"<ad user>",
"<ad pass>"))
{
using (var aduser = new UserPrincipal(ad, "dummy", "password", false))
{
aduser.Save();
}
}
但是,我收到RPC Unavailable
错误代码的消息{。}}。
有没有人见过它?
而且,更多的重要性,解决了它!
答案 0 :(得分:1)
这实际上是一般的域设置问题。我打赌你也无法使用Active Directory用户和计算机MMC管理单元从你的机器创建一个新用户。我建议您下载Windows 2003 Admin tools或Windows 2008 Remote Server Administration Tool并尝试先从您的计算机上手动完成。
一旦您证明这是一般性域设置问题,我认为您可以尝试在ServerFault.com上发布您的问题。你会得到更快更好的回答。
在许多AD操作(如密码重置)中,操作是通过MS-RPC完成的,而不是LDAP。因此,在创建新的AD用户时看到RPC server unavailable
错误消息并不奇怪。
导致RPC server unavailable
的原因有很多,您可以查看MSDN articile并查看是否有运气。
如果之前没有设置Active Directory,请输入以下基本信息。
1)您需要确保使用正确的DNS服务器。 Active Directory在DNS上存储了大量有用的信息。这不仅仅是您的域名和PDC名称。它有一些服务记录。如果目标PDC只是您设置的测试域,则许多程序员错误地只修改本地主机文件以将PDC解析为IP地址。这样做不会起作用,并会在路上造成一些麻烦。
2)您需要确保开发计算机上的时钟与PDC同步。 Kerberos身份验证对时间敏感。 Active Directory正在使用Kerberos身份验证。这通常不会成为问题,但有些程序员喜欢使用VM。如果你在同一台主机上运行很多虚拟机,我看到有一些时间滞后。
3)确保PDC上的RPC服务真正运行且未被防火墙阻止。如果您正在访问生产域,网络管理员可能会因严重原因阻止对端口135的访问。
这些是我能给出的最佳建议。希望这可以帮助。如果以上都没有帮助,我认为你必须通过查看网络数据包来解决它。使用wireshark捕获网络跟踪。在构建ContextOptions.SimpleBind
PrincipalContext
来修改代码以避免使用加密
最糟糕的是,虽然 上面的代码不起作用,做的 通过LDAP查询同样的事情就像 魅力
System.DirectoryService.AccountManagement
namepsace在内部使用DirectoryEntry
。 DirectoryEntry
在内部使用ADSI。 ADSI有一个复杂的逻辑来设置用户的密码。有三种方法可以在Active Directory中设置用户密码,顺序如下
除非配置了SSL,否则ADSI不会使用LDAP密码更新。不幸的是,SSL没有正确配置。您需要进行额外配置才能使其正常工作。它没有配置,因为Windows本身根本不需要使用SSL。它有Kerberos工作得很好。因此,在您的情况下,我打赌不会使用选项1.
选项2不起作用,因为您没有指向正确的DNS。您正在使用自己的本地主机文件。
现在,进入选项3,只有在允许当前线程安全上下文的情况下,调用才能成功。根据您的描述,听起来您的工作站根本没有加入该目标域。所以,我不指望你有Kerberos令牌。通常,它应该回退使用NTLM。如果您的域用户具有与工作站中使用的用户帐户相同的用户名和密码,则该用户应该可以使用。您还需要确保域用户帐户具有适当的权限。无论如何,这是我的知识。
事实是你得到了RPC server unavailable
。你必须失败这三个选项。
是的,您通过使用LDAP查询使其工作。也许,它的工作原理只是因为您使用的是简单的LDAP而根本没有SSL。这意味着你的密码是纯文本格式的。
我的建议是修复您的工作站以使用该域控制器上的DNS。一切都应该有效。
<强>已更新强>
在回复您之前,我没有阅读您发布的解决方案。如果DirectoryEntry
方法有效,我不明白为什么AccountManagement
方法不起作用。要了解其中的差异,我们可能需要对其进行反汇编。
答案 1 :(得分:1)
虽然.NET 3.5提供的AccountManagement接口不能解决我的问题,但是回归到忠实的LDAP工作。所以我在这里发帖给后人。
/*
* First we need to create the user...
*/
using (var dirEntry = new DirectoryEntry("LDAP://<IP/name>",
"<admin>",
"<admin pass>",
AuthenticationTypes.ServerBind))
{
using (var newUser = dirEntry.Children.Add("CN=dummy", "user"))
{
newUser.Properties["samAccountName"].Value = "dummy";
newUser.CommitChanges();
}
}
/*
* Then set its password!
*
* If the password is set in the same
* transaction as the creation an error occurr.
*/
using (var user = new DirectoryEntry("LDAP://<IP/name>/CN=dummy,DC=corp",
"<admin>",
"<admin pass>"))
{
user.Invoke("SetPassword", new object[] { "password" });
user.CommitChanges();
}