我有一个用于批量创建用户的应用程序(我知道这是非典型的,但不是我的决定(,目前,密码的验证只是使用正则表达式完成的。但具体要求可能会根据电脑的设置而变化,对吧?那么,有没有一种方法可以根据C#中的PC密码策略来测试给定的字符串?我想做一些类似的事情:
bool isPasswordGood = TestPasswordComplexity("notAgoodPassword");
这将取决于在Windows中设置的安全策略。这通常是使用GUI来设置安全策略的,但您实际上可以从命令行导出设置,如下所示:
secedit.exe /export /cfg C:tempMySecurityPolicy.inf
注意:您可能需要以管理员身份运行命令提示符才能允许(右键单击命令提示符图标并选择以管理员身份运行(。
这应该将您的设置保存在一个文本文件中(此处,MySecurityPolicy.inf(。该文件的第一部分应该如下所示:
[Unicode]
Unicode=yes
[System Access]
MinimumPasswordAge = 0
MaximumPasswordAge = 365
MinimumPasswordLength = 12
PasswordComplexity = 0
PasswordHistorySize = 20
LockoutBadCount = 20
ResetLockoutCount = 10
LockoutDuration = 10
RequireLogonToChangePassword = 0
ForceLogoffWhenHourExpire = 1
NewAdministratorName = "LocalAdmin"
NewGuestName = "LocalGuest"
ClearTextPassword = 0
(...)
特别地,我会想象第6&7,MinimumPasswordLength
和PasswordComplexity
将感兴趣-这里有一些关于的文档
一旦你了解了这是如何工作的,你就应该能够创建一个简单的脚本或程序来从这样的配置文件中读取,并使用其中的信息来通知你的密码验证方法。也许仅仅读第6&7.
我意识到这可能不如直接从C#中查找策略设置好,但它至少会给你一个选择:现在,每当你需要检查需求时,运行一个将设置导出到已知文件的脚本,并从你的应用程序中重新评估它。
如果你也可以从你的应用程序中运行导出过程(假设提升的权限要求不会造成麻烦(,那么你应该能够自动化所有这些。否则,您可能需要手动导出策略文件,并将其存储在应用程序可以读取的位置。
您想要的API函数是NetValidatePasswordPolicy。
它有三种操作模式:
-
NetValidateAuthentication
:如果您正在对用户进行身份验证;因此,该功能可以检查密码过期策略、错误登录尝试、帐户锁定、错误登录企图等 -
NetValidatePasswordChange
:如果用户正在更改密码;因此,该功能可以根据锁定或密码策略进行检查
和您想要的模式:
-
NetValidatePasswordReset
:您是重置用户密码的管理员;其仅检查密码复杂性
我将尝试从另一种语言转换为C#;但你必须P/Invoke它。
<summary>Check password during password reset.
The result from NetValidatePasswordReset, this member can be one of the following values.
NERR_Success The password passes the validation check.
NERR_PasswordTooShort Validation failed. The password does not meet policy requirements because it is too short.
NERR_PasswordTooLong Validation failed. The password does not meet policy requirements because it is too long.
NERR_PasswordNotComplexEnough Validation failed. The password does not meet policy requirements because it is not complex enough.
NERR_PasswordFilterError Validation failed. The password does not meet the requirements of the password filter DLL.
</summary>
UInt32 TestPasswordComplexity(String username, SecureString password)
{
//All code on stack overflow is in the public domain; no attribution
//is required.
const UInt32 NetValidatePasswordReset = 3;
NET_VALIDATE_PASSWORD_RESET_INPUT_ARG args = new NET_VALIDATE_PASSWORD_RESET_INPUT_ARG();
args.UserAccountName = Username; //some policies check that your password cannot contain your username
args.ClearPassword = SecureStringToString(password);
PNET_VALIDATE_OUTPUT_ARG res;
DWORD le = NetValidatePasswordPolicy(null, null, NetValidatePasswordReset, @args, {out}Pointer(res));
if (le <> NERR_Success)
throw new WindowsException(le); //
return res.ValidationStatus;
}