Passay是一个基于Java的密码生成和验证库。
Passay的API拥有3个核心组件
- Rule:一个或多个的密码策略规则集合
- PasswordValidator:密码验证器,根据规则对密码进行验证
- PasswordGenerator:密码生成器,生成满足规则的密码
规则
规则是密码生成和验证的基础,分为两类
- 正匹配规则:要求密码满足规则
- 否定匹配规则:拒绝满足规则的密码
正匹配规则
AllowedCharacterRule
要求密码包含一组字符的所有字符
AllowedRegexRule
要求密码符合正则表达式
CharacterCharacteristicsRule
要求密码复核N类字符中的M,如以下4个中的三个:digit(数字), upper-case letters(大写字母), lower-case letters(小写字母), symbols(符号)
CharacterRule
要求密码至少包含给定字符集中的 N 个字符
LengthRule
要求密码满足所需的最小长度
LengthComplexityRule
要求密码满足基于密码长度的特定规则集。例如,长度在 8-12 个字符之间的密码必须同时包含数字和符号。密码 13 个字符及以上,只能包含字母字符
否定匹配规则
- 字典规则
- 历史记录规则
字符事件规则
- 拒绝包含太多相同字符的密码非法字符规则
- 拒绝包含一组字符中的任何一个的密码非法正则表达式规则
- 拒绝符合正则表达式的密码非法序列规则
- 拒绝包含 N 个字符序列的密码(例如 12345)NumberRangeRule
- 拒绝包含定义范围内任何数字的密码(例如 1000-9999)- 源规则
SourceRule
- 拒绝与来自其他源的密码匹配的密码(明文比较)DigestSourceRule
- 拒绝与来自其他来源的摘要相匹配的密码(哈希/摘要比较)
重复字符正则规则
- 拒绝包含重复 ASCII 字符的密码重复字符规则
- 拒绝包含多个重复字符序列的密码用户名规则
- 拒绝包含提供密码的用户的用户名的密码空格规则
- 拒绝包含空格字符的密码
密码校验
密码校验采用PasswordValidator
进行
PasswordValidator passwordValidator = new PasswordValidator(
// 长度 8-30位
new LengthRule(8, 30),
// 至少一个大写字母
new CharacterRule(EnglishCharacterData.UpperCase, 1),
// 至少一个小写字母
new CharacterRule(EnglishCharacterData.LowerCase, 1),
// 至少一个特殊字符
new CharacterRule(EnglishCharacterData.Special, 1),
// 至少一个数字
new CharacterRule(EnglishCharacterData.Digit, 1),
// 不允许连续5个字母
new IllegalSequenceRule(EnglishSequenceData.Alphabetical, 5, false),
// 不允许连续5个数字
new IllegalSequenceRule(EnglishSequenceData.Numerical, 5, false),
// 不允许键盘上的连续5个键
new IllegalSequenceRule(EnglishSequenceData.USQwerty, 5, false),
// 不允许空白字符
new WhitespaceRule()
);
// 校验的密码要用PasswordData包装
RuleResult ruleResult = passwordValidator.validate(new PasswordData("sdfhusdifi"));
// 判断是否校验通过
if (ruleResult.isValid()) {
System.out.println("password valid");
}else {
// 打印校验不通过的规则
List<String> messages = passwordValidator.getMessages(ruleResult);
System.out.println(String.join("\n",messages));
}
Password must contain 1 or more uppercase characters.
Password must contain 1 or more special characters.
Password must contain 1 or more digit characters.
自定义消息
Passay提供MessageResolver
接口,允许将密码验证结果任意转换为自定义的文本,以便向用户显示。
默认Message
HISTORY_VIOLATION=Password matches one of %1$s previous passwords.
ILLEGAL_WORD=Password contains the dictionary word '%1$s'.
ILLEGAL_WORD_REVERSED=Password contains the reversed dictionary word '%1$s'.
ILLEGAL_DIGEST_WORD=Password contains a dictionary word.
ILLEGAL_DIGEST_WORD_REVERSED=Password contains a reversed dictionary word.
ILLEGAL_MATCH=Password matches the illegal pattern '%1$s'.
ALLOWED_MATCH=Password must match pattern '%1$s'.
ILLEGAL_CHAR=Password %2$s the illegal character '%1$s'.
ALLOWED_CHAR=Password %2$s the illegal character '%1$s'.
ILLEGAL_QWERTY_SEQUENCE=Password contains the illegal QWERTY sequence '%1$s'.
ILLEGAL_ALPHABETICAL_SEQUENCE=Password contains the illegal alphabetical sequence '%1$s'.
ILLEGAL_NUMERICAL_SEQUENCE=Password contains the illegal numerical sequence '%1$s'.
ILLEGAL_USERNAME=Password %2$s the user id '%1$s'.
ILLEGAL_USERNAME_REVERSED=Password %2$s the user id '%1$s' in reverse.
ILLEGAL_WHITESPACE=Password %2$s a whitespace character.
ILLEGAL_NUMBER_RANGE=Password %2$s the number '%1$s'.
ILLEGAL_REPEATED_CHARS=Password contains %3$s sequences of %1$s or more repeated characters, but only %2$s allowed: %4$s.
INSUFFICIENT_UPPERCASE=Password must contain %1$s or more uppercase characters.
INSUFFICIENT_LOWERCASE=Password must contain %1$s or more lowercase characters.
INSUFFICIENT_ALPHABETICAL=Password must contain %1$s or more alphabetical characters.
INSUFFICIENT_DIGIT=Password must contain %1$s or more digit characters.
INSUFFICIENT_SPECIAL=Password must contain %1$s or more special characters.
INSUFFICIENT_CHARACTERISTICS=Password matches %1$s of %3$s character rules, but %2$s are required.
INSUFFICIENT_COMPLEXITY=Password meets %2$s complexity rules, but %3$s are required.
INSUFFICIENT_COMPLEXITY_RULES=No rules have been configured for a password of length %1$s.
SOURCE_VIOLATION=Password cannot be the same as your %1$s password.
TOO_LONG=Password must be no more than %2$s characters in length.
TOO_SHORT=Password must be %1$s or more characters in length.
TOO_MANY_OCCURRENCES=Password contains %2$s occurrences of the character '%1$s', but at most %3$s are allowed.
加载自定义的消息配置
Properties props = new Properties();
props.load(new FileInputStream("/path/to/passay.properties"));
MessageResolver resolver = new PropertiesMessageResolver(props);
PasswordValidator validator = new PasswordValidator(
resolver, new LengthRule(8, 16), new WhitespaceRule());
passay也实现了基于Spring的SpringMessageResolver
,可以将Spring的MessageSource
直接配置进去
@Bean
public MessageResolver messageResolver() {
return new SpringMessageResolver(messageSource);
}
@Resource
private SpringMessageResolver springMessageResolver;
...
new PasswordValidator(springMessageResolver,new LengthRule(8, 16), new WhitespaceRule());
高级验证
N个规则中的M个
CharacterCharacteristicsRule characterCharacteristicsRule = new CharacterCharacteristicsRule();
// 至少满足3个规则
characterCharacteristicsRule.setNumberOfCharacteristics(3);
// 至少一个大写字母
characterCharacteristicsRule.getRules().add(new CharacterRule(EnglishCharacterData.UpperCase, 1));
// 至少一个小写字母
characterCharacteristicsRule.getRules().add(new CharacterRule(EnglishCharacterData.LowerCase, 1));
// 至少一个特殊字符
characterCharacteristicsRule.getRules().add(new CharacterRule(EnglishCharacterData.Special, 1));
// 至少一个数字
characterCharacteristicsRule.getRules().add(new CharacterRule(EnglishCharacterData.Digit, 1));
PasswordValidator passwordValidator = new PasswordValidator(
// 长度 8-30位
new LengthRule(8, 30),
// N个规则验证M个
characterCharacteristicsRule,
// 不允许空白字符
new WhitespaceRule()
);
RuleResult ruleResult = passwordValidator.validate(new PasswordData("Aaaaaaaaaa"));
if (ruleResult.isValid()) {
System.out.println("password valid");
}else {
List<String> messages = passwordValidator.getMessages(ruleResult);
System.out.println(String.join("\n",messages));
}
字典规则
许多密码策略旨在防止常用词(例如password)出现在密码中。
Passay附带了两个规则,可以与任意单词列表一起使用,以执行字典策略
DictionaryRule
- 精确匹配语义DictionarySubstringRule
- 包含匹配的语义
DictionaryRule
:防止已知的弱密码。使用已发布的常用密码列表(例如来自 Adobe 违规的密码)配置此规则,可以通过防止常见且因此不安全的密码来显著提高密码安全性。
DictionarySubstringRule
应该明智地使用,只要密码中包含配置项,则会被拒绝。
DictionarySubstringRule dictionarySubstringRule =
new DictionarySubstringRule(new WordListDictionary(new ArrayWordList(new String[]{"password"})));
PasswordValidator passwordValidator = new PasswordValidator(dictionarySubstringRule);
RuleResult ruleResult = passwordValidator.validate(new PasswordData("password123"));
System.out.println(ruleResult.isValid()); // false
DictionaryRule dictionaryRule =
new DictionaryRule(new WordListDictionary(new ArrayWordList(new String[]{"password"})));
passwordValidator = new PasswordValidator(dictionaryRule);
ruleResult = passwordValidator.validate(new PasswordData("password123"));
System.out.println(ruleResult.isValid()); // true
官方示例:
DictionaryRule rule = new DictionaryRule(
new WordListDictionary(WordLists.createFromReader(
// Reader around the word list file
new FileReader[] {new FileReader("path/to/top100.txt")},
// True for case sensitivity, false otherwise
false,
// Dictionaries must be sorted
new ArraysSort())));
密码生成
密码生成采用PasswordGenerator
进行
List<CharacterRule> rules = Arrays.asList(
// 最少一个大写字母
new CharacterRule(EnglishCharacterData.UpperCase, 1),
// 最少一个小写字母
new CharacterRule(EnglishCharacterData.LowerCase, 1),
// 最少一个数字
new CharacterRule(EnglishCharacterData.Digit, 1)
);
PasswordGenerator generator = new PasswordGenerator();
// 15位长度
String password = generator.generatePassword(15, rules);
System.out.println(password);