我的目标很简单:预先验证新密码客户端(Javascript)作为初始检查密码与域/ ou密码策略匹配,以避免浪费服务器资源拒绝错误密码并给用户更快的响应。
问题:如何从Active Directory获取用户密码策略?
我特别需要知道密码“格式”,密码长度,资本和特殊字符要求等。最后的验证当然是Active Directory本身。但首先我想使用Javascript作为性能优化,如果我能在C#/ ASP.Net端检索特定用户/ OU的密码格式要求,我很确定我可以管理Javascript。
目前,我一直试图找到当前密码策略对用户的影响。是的,用户Alice
可能会使用密码域策略,但Bob
可能在其OU中使用不同的密码策略。
该网站将安装在拥有数千名用户的机构中;我们希望最小化针对Active Directory的来回验证。此外,在Javascript中使用此功能最终可以帮助符合NIST Special Publication 800-63,其中包括要求用户提供相对密码强度的快速反馈。目前,我必须能够使代码在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
)并读取这些属性:
minPwdLength
:最小字符长度pwdHistoryLength
:无法重复使用的旧密码数。pwdProperties
:这是一个可能意味着各种各样的东西,你可以在“PasswordProperties”部分here下阅读。它可能设置为1(DOMAIN_PASSWORD_COMPLEX
),这意味着密码必须包含至少两个大写,小写和数字。如果您想要阅读适用于用户OU的组策略,那么似乎没有任何.NET库可以执行此操作。您必须使用非托管代码。有一个示例here使用C#的IGPMDomain
接口,但您必须调整它以找到正确OU的GPO。