我坚持使用UserPrincipal类来操作AD-LDS用户对象。虽然我可以查询用户,更改属性并将其保存回AD LDS,但一旦我尝试设置(或更改)密码,我总是会得到一个PrincipalOperationException
,其中包含附加信息“目录属性无法在缓存中找到。“
如果我通过ADSI-Edit更改用户密码,一切正常。因此,我认为这不是架构问题。我绑定简单绑定而没有SSL(它是一个开发机器)。我通过dsmgmt允许不安全的密码设置选项。我用来连接的用户位于用户所在目录配置单元的admin-role中。 代码看起来像这样(简化):
using (var ctx = GetPrincipalContext()) {
UserPrincipal u = UserPrincipal.FindByIdentity(ctx, IdentityType.Name, identityValue);
u.SetPassword("12345$äöAAA1234_");
u.Save();
}
在GetPrincipalContext()中创建上下文,如下所示:
new PrincipalContext(ContextType.ApplicationDirectory, "localhost", "[DC=...]", ContextOptions.SimpleBind,"[username of adminuser]","[Password of admin user]");
当我尝试创建一个新的UserPrincipal然后保存它时,会出现同样的问题。我认为,这也是因为附加了密码。
答案 0 :(得分:4)
总而言之,这是一个安全问题。只要未通过SSL建立与AD-LDS的连接,处理密码的所有内容都会令人头疼。
在找到初始问题的解决方案后(见下文),我得出的结论是,安装带证书的AD-LDS远比尝试解决配置中出现的所有问题要高效得多。 SSL(即使在开发中)。因此,我建议所有想要使用AD-LDS的人来完成安装开发证书的额外工作。这样做的复杂性低于解决在没有SSL的情况下出现的所有问题的复杂性。经过一些谷歌搜索后,我能够使用windows sdk的makecert-programm创建和安装必要的证书。
对于那些对解决方案感兴趣的人:
在阅读了很多关于AD-LDS及其验证方式的内容后,我的理解是无法使用不带SSL的UserPrincipal类设置密码。作为解决方法,DirectoryEntry-class可用于通过LDAP调用SetPassword-methdod。但是它需要一些参数化:
const long ADS_OPTION_PASSWORD_PORTNUMBER = 6;
const long ADS_OPTION_PASSWORD_METHOD = 7;
const int ADS_PASSWORD_ENCODE_CLEAR = 1;
directoryEntry.Invoke("SetOption", new object[] { ADS_OPTION_PASSWORD_PORTNUMBER, intPort });
directoryEntry.Invoke("SetOption", new object[] { ADS_OPTION_PASSWORD_METHOD, ADS_PASSWORD_ENCODE_CLEAR});
directoryEntry.Invoke("SetPassword", new object[] { "MyPassword" });
此外,有必要通过dsmgmt命令行工具允许unsave密码通信。
对正在发生的事情的理解,我从这本书的在线预览中得到The .Net Developer's Guide to Directory Services Programming虽然我可能不再需要这本书,但我命令它捐赠作者,他救了我几个小时搜索虽然它已经很老了,但这本书包含了关于AD LDS(ADAM)的非常好的解释,它们现在仍然具有相关性。
答案 1 :(得分:-1)
有一种设置密码的方法,但您需要更改 ADLDS 设置以允许在不安全的频道上设置密码。
cmd\
dsmgmt\
ds behavior\
connections\
connect to server localhost:389\
quit\
allow passwd op on unsecured connection\
quit\
quit