Проверьте сложность пароля с Active Directory в C#
Я пишу установщик, который устанавливает 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);
}
2 ответа
После большой боли я нашел решение C# для этого, используя 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);
}
}
}
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
}