无法使用 UserPrincipal 类设置 AD-LDS 用户密码

Posted

技术标签:

【中文标题】无法使用 UserPrincipal 类设置 AD-LDS 用户密码【英文标题】:Can not set AD-LDS user-password with the UserPrincipal-class 【发布时间】:2014-05-26 16:48:11 【问题描述】:

我被 UserPrincipal 类操作 AD-LDS 用户对象所困扰。虽然我可以查询用户、更改属性并将它们保存回 AD LDS,但只要我尝试设置(或更改)密码,我总是会收到带有附加信息的 PrincipalOperationException“目录属性不能在缓存中找到。”

如果我通过 ADSI-Edit 更改用户密码,一切正常。因此我认为这不是模式问题。我使用简单绑定而不使用 SSL 进行绑定(它是一个开发机器)。我已经通过 dsmgmt 允许了不安全的密码设置选项。我用来连接的用户是用户所在目录配置单元的管理员角色。 代码如下所示(简化):

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 然后保存它时,也会出现同样的问题。我想,这也是因为附加的密码。

【问题讨论】:

【参考方案1】:

长话短说,这是一个安全问题。只要不是通过 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-命令行工具允许取消保存密码通信。

对发生的事情的了解,我从本书的在线预览中得到了The .Net Developer's Guide to Directory Services Programming 虽然我可能不再需要这本书了,但我下令将其捐赠给作者,他为我节省了数小时的搜索时间.这本书虽然年代久远,但对 AD LDS (ADAM) 进行了很好的解释,这些解释至今仍然适用。

【讨论】:

嘿,很好的答案,如果您可以在调用 SetPassword 操作之前填写有关您设置的选项的更多信息,那就太好了。尤其是第二个。 对不起,我太久没有这样做了。我已经不记得细节了。【参考方案2】:

有一种设置密码的方法,但您需要更改 ADLDS 设置以允许在不安全的频道上设置密码。

cmd\
dsmgmt\
ds behavior\
connections\
connect to server localhost:389\
quit\
allow passwd op on unsecured connection\
quit\
quit

【讨论】:

以上是关于无法使用 UserPrincipal 类设置 AD-LDS 用户密码的主要内容,如果未能解决你的问题,请参考以下文章

为什么我们必须等待一段时间才能从UserPrincipal.GetAuthorizationGroups方法获取最新的组信息?

UserPrincipal.FindByIdentity 在 64 位 WinPE 下的 C# 中失败

UserPrincipal.GetGroups vs. UserPrincipal.GetAuthorizationGroups?

UserPrincipal.GetAuthorizationGroups() 方法出错

按日期时间自定义属性搜索 Active Directory (AD LDS)

检查Windows用户是否存在其中一个AD组(ADgroup1,AD group2,ADgroup3等)