如何描述 PasswordValidator 规则
How to describe PasswordValidator rules
Microsoft.AspNet.Identity.PasswordValidator 可配置多个参数,这些参数定义最小密码长度和复杂性规则。如果用户输入的密码不符合标准,PasswordValidator 将抛出一个描述违规的异常,但它没有提供其他方式向用户描述规则(例如 "Passwords must be 8-12 characters and must include ..." 等)。
我搜索了 Whosebug 和网络,发现那里肯定有数百个我需要的例子,但它开始看起来像我是唯一一个需要这个的人,我知道这不是'不是这样的。在我编写自己的实现之前,我只需要问...
我是否完全忽略了这个问题的公认 "standard" 答案?
这听起来可能有点老套,但是向 PasswordValidator 的 ValidateAsync() 方法发送一个空字符串就可以了。默认配置的 UserManager 示例:
var rules = await UserManager.PasswordValidator.ValidateAsync("");
rules.Errors.First() :
Passwords must be at least 6 characters.
Passwords must have at least one non letter or digit character.
Passwords must have at least one digit ('0'-'9').
Passwords must have at least one lowercase ('a'-'z').
Passwords must have at least one uppercase ('A'-'Z').
你甚至可以列出它们
var list = rules.Errors.First().Split('.');
这是我想出的,因为我需要让一些东西工作,但没有找到我正在寻找的标准答案。为了方便起见,我将其实现为 PasswordValidator class 的扩展,尽管这并非绝对必要。
public static string ToDescription(this PasswordValidator validator)
{
var options = new List<string>();
if (validator.RequireUppercase) options.Add("upper-case letters");
if (validator.RequireLowercase) options.Add("lower-case letters");
if (validator.RequireDigit) options.Add("numbers");
if (validator.RequireNonLetterOrDigit) options.Add("special characters");
var result = "Passwords must be at least "
+ validator.RequiredLength + " characters long"
+ (options.Any() ? ", and include " + options.OxfordJoin() : ".");
return result;
}
我还添加了 OxfordJoin 扩展以将需求列表转换为格式良好的句子:
public static string OxfordJoin(this IEnumerable<string> source)
{
var array = source.ToArray();
var joined = string.Join(", ", array);
var result = (array.Length > 2)
? joined.ReplaceLast(",", ", and")
: joined.ReplaceLast(",", " and");
return result;
}
...最后是 "so standard it should just be in the framework already" ReplaceLast 实现:
public static string ReplaceLast(this string value, string oldValue, string newValue)
{
var position = value.LastIndexOf(oldValue, StringComparison.InvariantCultureIgnoreCase);
var result = (position > -1)
? value.Substring(0, position) + newValue + value.Substring(position + 1)
: value;
return result;
}
Microsoft.AspNet.Identity.PasswordValidator 可配置多个参数,这些参数定义最小密码长度和复杂性规则。如果用户输入的密码不符合标准,PasswordValidator 将抛出一个描述违规的异常,但它没有提供其他方式向用户描述规则(例如 "Passwords must be 8-12 characters and must include ..." 等)。
我搜索了 Whosebug 和网络,发现那里肯定有数百个我需要的例子,但它开始看起来像我是唯一一个需要这个的人,我知道这不是'不是这样的。在我编写自己的实现之前,我只需要问...
我是否完全忽略了这个问题的公认 "standard" 答案?
这听起来可能有点老套,但是向 PasswordValidator 的 ValidateAsync() 方法发送一个空字符串就可以了。默认配置的 UserManager 示例:
var rules = await UserManager.PasswordValidator.ValidateAsync("");
rules.Errors.First() :
Passwords must be at least 6 characters.
Passwords must have at least one non letter or digit character.
Passwords must have at least one digit ('0'-'9').
Passwords must have at least one lowercase ('a'-'z').
Passwords must have at least one uppercase ('A'-'Z').
你甚至可以列出它们
var list = rules.Errors.First().Split('.');
这是我想出的,因为我需要让一些东西工作,但没有找到我正在寻找的标准答案。为了方便起见,我将其实现为 PasswordValidator class 的扩展,尽管这并非绝对必要。
public static string ToDescription(this PasswordValidator validator)
{
var options = new List<string>();
if (validator.RequireUppercase) options.Add("upper-case letters");
if (validator.RequireLowercase) options.Add("lower-case letters");
if (validator.RequireDigit) options.Add("numbers");
if (validator.RequireNonLetterOrDigit) options.Add("special characters");
var result = "Passwords must be at least "
+ validator.RequiredLength + " characters long"
+ (options.Any() ? ", and include " + options.OxfordJoin() : ".");
return result;
}
我还添加了 OxfordJoin 扩展以将需求列表转换为格式良好的句子:
public static string OxfordJoin(this IEnumerable<string> source)
{
var array = source.ToArray();
var joined = string.Join(", ", array);
var result = (array.Length > 2)
? joined.ReplaceLast(",", ", and")
: joined.ReplaceLast(",", " and");
return result;
}
...最后是 "so standard it should just be in the framework already" ReplaceLast 实现:
public static string ReplaceLast(this string value, string oldValue, string newValue)
{
var position = value.LastIndexOf(oldValue, StringComparison.InvariantCultureIgnoreCase);
var result = (position > -1)
? value.Substring(0, position) + newValue + value.Substring(position + 1)
: value;
return result;
}