System.DirectoryServices.AccountManagement 和来自 LDAP 与 LDAPS 的错误消息

System.DirectoryServices.AccountManagement and error messages from LDAP vs LDAPS

我有一些使用 System.DirectoryServices.AccountManagement 的 C# 代码,用于允许用户更改其 Active Directory 用户帐户密码。它目前正在使用 LDAP (:389),出于安全目的,我想将其切换到 LDAPS (:636)。但是,当我切换到 LDAPS 时,返回给我的错误消息发生了变化并且变得不太有用。

问题简述如下:

如果我使用 LDAP (:389) 连接,我会使用以下 ConextOptions

ContextOptions.Negotiate | ContextOptions.ServerBind | ContextOptions.Signing

如果我使用 LDAPS (:636) 连接,我会使用以下 ContextOptions

ContextOptions.Negotiate | ContextOptions.ServerBind | ContextOptions.SecureSocketLayer

如果用户提供正确的当前密码和有效的新密码,任何一个版本都可以更改密码。但是,例如,在用户输入错误的当前密码的情况下,我收到的错误消息是不同的,并且在 LDAPS 的情况下用处不大:

LDAP(:389) :

The specified network password is not correct. (Exception from HRESULT: 0x80070056)

LDAPS(:636) :

A constraint violation occurred. (Exception from HRESULT: 0x8007202F)

差异的关键似乎是 ContextOptions.Signing - 如果我没有为 LDAP(:389) 连接指定这一点,我会收到与 LDAPS(:636) 相同的错误消息。但是,如果我为 LDAPS 指定 ContextOptions.Signing,DC 将拒绝响应。

根据这篇文章,这似乎是 LDAPS 的最佳选择:https://blogs.msdn.microsoft.com/dsadsi/2012/06/06/changepassword-and-password-complexity-violation-error-codes/

要解决此问题,您可以在实际执行密码更改之前进行一些验证,例如:

  • 使用当前提供的密码验证帐户是否正确
  • 查找密码策略以验证:
    • 新密码复杂度
    • 现有密码的最小使用期限(检查密码最后更改的属性)

这很痛苦,但如果您事先进行了所有这些检查,则可以为您的用户提供更具描述性的错误消息。

尽管您将无法验证新密码之前是否未被使用过。