C# 如何在Active Directory中对密码更改进行客户端验证

C# 如何在Active Directory中对密码更改进行客户端验证,c#,active-directory,C#,Active Directory,我的目标很简单:在初始检查密码是否与域/ou密码策略匹配时预先验证新密码客户端(Javascript),以避免浪费服务器资源拒绝错误密码,并为用户提供更快的响应 问题:如何从Active Directory获取用户密码策略? 我特别需要知道密码的“格式”、密码长度、大写字母和特殊字符要求等。当然,最终的验证将是Active Directory本身。但首先,我想将Javascript用作性能优化,如果我能在C#/ASP.Net端检索特定用户/OU的密码格式要求,我相信我可以管理Javascript

我的目标很简单:在初始检查密码是否与域/ou密码策略匹配时预先验证新密码客户端(Javascript),以避免浪费服务器资源拒绝错误密码,并为用户提供更快的响应

问题:如何从Active Directory获取用户密码策略?

我特别需要知道密码的“格式”、密码长度、大写字母和特殊字符要求等。当然,最终的验证将是Active Directory本身。但首先,我想将Javascript用作性能优化,如果我能在C#/ASP.Net端检索特定用户/OU的密码格式要求,我相信我可以管理Javascript

目前,我一直在尝试查找用户的当前密码策略。是的,用户
Alice
可能使用密码域策略,但是
Bob
可能在其OU中使用不同的密码策略

该网站将安装在一个拥有数千用户的机构中;我们希望最小化对Active Directory的来回验证。此外,在Javascript中使用此选项最终有助于遵守,这要求用户及时反馈相对密码强度。目前,我必须能够使代码在Windows 2008、2008 R2和2012上运行

我目前可以在C#中更改密码,并且我可以得到错误,但这是全有或全无,对客户端验证没有帮助

public static PasswordChangeResultsDTO ChangeUserPassword(PasswordChangeRequestDTO request)
{
    try
    {
        bool isPasswordChanged = false;
        SearchResult result = LdapHelper.GetUser(request.Username, request.OldPassword);

        if (result != null)
        {
            using (DirectoryEntry userEntry = result.GetDirectoryEntry())
            {
                userEntry.Invoke("ChangePassword", new object[] {request.OldPassword, request.NewPassword});
                userEntry.CommitChanges();
                isPasswordChanged = true;
            }
        }

        return new PasswordChangeResultsDTO {PasswordChanged = isPasswordChanged};
    }
    catch (COMException comException)
    {
        LoggingHelper.Instance.WriteException(comException);
        string message = comException.ErrorCode == -2147022651
                             ? "The password does not meet the password policy requirements"
                             : comException.Message;
        return new PasswordChangeResultsDTO {PasswordChanged = false, Message = message};
    }
    catch (TargetInvocationException targetInvocationException)
    {
        LoggingHelper.Instance.WriteException(targetInvocationException);
        string message;
        if (targetInvocationException.InnerException != null)
        {
            var comException = targetInvocationException.InnerException as COMException;
            if (comException != null)
            {
                message = comException.ErrorCode == -2147022651
                          ? "The password does not meet the password policy requirements"
                          : comException.Message;
            }
            else
            {
                message = targetInvocationException.InnerException.Message;
            }
        }
        else
        {
            message = targetInvocationException.Message;
        }

        return new PasswordChangeResultsDTO {PasswordChanged = false, Message = message};
    }
    catch (Exception ex)
    {
        string msgError = (null != ex.InnerException) ? ex.InnerException.Message : ex.Message;
        string msgSource = (null != ex.InnerException) ? ex.InnerException.Source : ex.Source;
        string msgStackTrace = (null != ex.InnerException) ? ex.InnerException.StackTrace : ex.StackTrace;
        string msgOutput = String.Format(CultureInfo.InvariantCulture,
                                             "Exception in {3} MSG[{0}] SOURCE[{1}] STACK[{2}]",
                                         msgError, msgSource, msgStackTrace, MethodBase.GetCurrentMethod().Name);

        LoggingHelper.Instance.Fatal(msgOutput);
        throw;
    }
}

在域级别查找此信息很容易。很难确定是否有任何组策略覆盖了默认值

在域级别,域本身有一些属性控制域的默认密码策略。您可以绑定到域本身(即
LDAP://domain.com
)并读取以下属性:

  • :最小字符长度
  • :无法重复使用的旧密码数
  • :这是一个位标志,可以表示各种内容,您可以在“PasswordProperties”部分中阅读。它可能被设置为1(
    DOMAIN\u PASSWORD\u COMPLEX
    ),这意味着密码必须至少包含大写、小写和数字中的两个

如果您想阅读将应用于用户OU的组策略,那么似乎没有任何.NET库可以做到这一点。您必须求助于使用非托管代码。有一个例子使用了C#中的接口,但您必须对其进行调整,以找到适合您的GPO。

在我看来,这将大大减少代码量。你甚至不能在客户端检查密码历史记录,所以你仍然要让服务器过滤掉坏密码。你预计用户设置密码的频率有多高,让服务器处理检查会降低他们的体验?很难说。。。昨天我找到了一个正则表达式,可以通过浏览器thaks对attibute进行验证。我的系统管理员告诉我Windows Server 2012具有更高的粒度,但我们这里还没有。。。