2

我正在编写一个安装 SQL 的安装程序,预先提示用户输入将为他们创建的 SA 用户名/密码。安装 SQL 时,它会根据 Active Directory 策略验证此密码,如果不匹配,则会失败。

我要做的是在继续安装 SQL 之前验证用户输入的密码是否有效。

如何根据 Active Directory 规则验证密码是否正确?

请注意,我没有根据此答案进行验证的登录名,而只是用于验证的密码。

我目前正在尝试这个,但是写我知道不允许的“密码”不会引发异常

try
{
    System.DirectoryServices.DirectoryEntry localMachine = new System.DirectoryServices.DirectoryEntry("WinNT://" + Environment.MachineName);
    ListPasswordPolicyInfo(Environment.MachineName);
    System.DirectoryServices.DirectoryEntry newUser = localMachine.Children.Add("localuser", "user");
    newUser.Invoke("SetPassword", new object[] { "3l!teP@$$w0RDz" });
    newUser.Invoke("SetPassword", new object[] { "password" });
    //newUser.CommitChanges();
    //Console.WriteLine(newUser.Guid.ToString());
    localMachine.Close();
    newUser.Close();
}
catch(Exception e)
{
    Console.WriteLine(e.Message);
}
4

2 回答 2

5

在经历了很多痛苦之后,我找到了使用NetValidatePasswordPolicy. 使用PInvoke的支持结构和以下代码

public static NET_API_STATUS ValidatePassword(string password)
{
    var outputArgs = new NET_VALIDATE_OUTPUT_ARG();
    var inputArgs = new NET_VALIDATE_PASSWORD_CHANGE_INPUT_ARG();

    IntPtr inputPointer = IntPtr.Zero;
    IntPtr outputPointer = IntPtr.Zero;

    try
    {
        inputArgs.PasswordMatched = true;
        inputArgs.ClearPassword = Marshal.StringToBSTR(password);

        // If using a secure string
        ////inputArgs.ClearPassword = Marshal.SecureStringToBSTR(secureStringPassword);

        inputPointer = Marshal.AllocHGlobal(Marshal.SizeOf(inputArgs));
        Marshal.StructureToPtr(inputArgs, inputPointer, false);

        NET_API_STATUS status = NetValidatePasswordPolicy(System.Environment.MachineName, IntPtr.Zero, NET_VALIDATE_PASSWORD_TYPE.NetValidatePasswordChange, inputPointer, ref outputPointer);

        if (status == NET_API_STATUS.NERR_Success)
        {
            outputArgs = (NET_VALIDATE_OUTPUT_ARG)Marshal.PtrToStructure(outputPointer, typeof(NET_VALIDATE_OUTPUT_ARG));

            if (outputArgs.ValidationStatus == NET_API_STATUS.NERR_Success)
            {
                // Ok
            }

            return outputArgs.ValidationStatus;
        }
        else
        {
            return status;
        }
    }
    finally
    {
        if (outputPointer != IntPtr.Zero)
        {
            NetValidatePasswordPolicyFree(ref outputPointer);
        }

        if (inputArgs.ClearPassword != IntPtr.Zero)
        {
            Marshal.ZeroFreeBSTR(inputArgs.ClearPassword);
        }

        if (inputPointer != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(inputPointer);
        }
    }
}
于 2014-01-29T13:55:32.093 回答
-1
try{    
var userName = "bob";
    using (var pc = new PrincipalContext(ContextType.Domain)
    {
          var user = UserPrincipal.FindByIdentity(pc, userName);
          user.ChangePassword(oldpassword, newpassword); //Checks password policy
          //or
          user.SetPassword(newpassword); //Not positive checks password policy but I believe it 2.
    }
}
catch(PasswordException ex)
{
//do something with ex
}
于 2014-01-28T16:29:30.710 回答