* BAEL-2165: Guide to Passay

* BAEL-2165: Guide to Passay #2

* BAEL-2165: Guide to Passay #3

Fixed formatting.
This commit is contained in:
Patryk 2018-09-29 10:52:02 +02:00 committed by Grzegorz Piwowarek
parent 51914a01e1
commit 56c2b9663e
6 changed files with 368 additions and 0 deletions

View File

@ -38,6 +38,16 @@
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.passay</groupId>
<artifactId>passay</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.cryptacular</groupId>
<artifactId>cryptacular</artifactId>
<version>1.2.2</version>
</dependency>
</dependencies>

View File

@ -0,0 +1,149 @@
package com.baeldung.passay;
import org.cryptacular.bean.EncodingHashBean;
import org.cryptacular.spec.CodecSpec;
import org.cryptacular.spec.DigestSpec;
import org.junit.Assert;
import org.junit.Test;
import org.passay.DictionaryRule;
import org.passay.DictionarySubstringRule;
import org.passay.DigestHistoryRule;
import org.passay.EnglishSequenceData;
import org.passay.HistoryRule;
import org.passay.IllegalCharacterRule;
import org.passay.IllegalRegexRule;
import org.passay.IllegalSequenceRule;
import org.passay.NumberRangeRule;
import org.passay.PasswordData;
import org.passay.PasswordValidator;
import org.passay.RepeatCharacterRegexRule;
import org.passay.RuleResult;
import org.passay.SourceRule;
import org.passay.UsernameRule;
import org.passay.WhitespaceRule;
import org.passay.dictionary.ArrayWordList;
import org.passay.dictionary.WordListDictionary;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
public class NegativeMatchingRulesUnitTest {
@Test
public void givenDictionaryRules_whenValidatePassword_thenFoundIllegalWordsFromDictionary() {
ArrayWordList arrayWordList = new ArrayWordList(new String[] { "bar", "foobar" });
WordListDictionary wordListDictionary = new WordListDictionary(arrayWordList);
DictionaryRule dictionaryRule = new DictionaryRule(wordListDictionary);
DictionarySubstringRule dictionarySubstringRule = new DictionarySubstringRule(wordListDictionary);
PasswordValidator passwordValidator = new PasswordValidator(dictionaryRule, dictionarySubstringRule);
RuleResult validate = passwordValidator.validate(new PasswordData("foobar"));
assertFalse(validate.isValid());
assertEquals("ILLEGAL_WORD:{matchingWord=foobar}", getDetail(validate, 0));
assertEquals("ILLEGAL_WORD:{matchingWord=bar}", getDetail(validate, 1));
}
@Test
public void givenHistoryRule_whenValidatePassword_thenFoundIllegalWordsFromHistory() {
HistoryRule historyRule = new HistoryRule();
PasswordData passwordData = new PasswordData("123");
passwordData.setPasswordReferences(new PasswordData.HistoricalReference("12345"), new PasswordData.HistoricalReference("1234"), new PasswordData.HistoricalReference("123"));
PasswordValidator passwordValidator = new PasswordValidator(historyRule);
RuleResult validate = passwordValidator.validate(passwordData);
assertFalse(validate.isValid());
assertEquals("HISTORY_VIOLATION:{historySize=3}", getDetail(validate, 0));
}
@Test
public void givenSeveralIllegalRules_whenValidatePassword_thenFoundSeveralIllegalPatterns() {
IllegalCharacterRule illegalCharacterRule = new IllegalCharacterRule(new char[] { 'a' });
IllegalRegexRule illegalRegexRule = new IllegalRegexRule("\\w{2}\\d{2}");
IllegalSequenceRule illegalSequenceRule = new IllegalSequenceRule(EnglishSequenceData.Alphabetical, 3, true);
NumberRangeRule numberRangeRule = new NumberRangeRule(1, 10);
WhitespaceRule whitespaceRule = new WhitespaceRule();
PasswordValidator passwordValidator = new PasswordValidator(illegalCharacterRule, illegalRegexRule, illegalSequenceRule, numberRangeRule, whitespaceRule);
RuleResult validate = passwordValidator.validate(new PasswordData("abcd22 "));
assertFalse(validate.isValid());
assertEquals("ILLEGAL_CHAR:{illegalCharacter=a, matchBehavior=contains}", getDetail(validate, 0));
assertEquals("ILLEGAL_MATCH:{match=cd22, pattern=\\w{2}\\d{2}}", getDetail(validate, 1));
assertEquals("ILLEGAL_ALPHABETICAL_SEQUENCE:{sequence=abc}", getDetail(validate, 2));
assertEquals("ILLEGAL_ALPHABETICAL_SEQUENCE:{sequence=bcd}", getDetail(validate, 3));
assertEquals("ILLEGAL_NUMBER_RANGE:{number=2, matchBehavior=contains}", getDetail(validate, 4));
assertEquals("ILLEGAL_WHITESPACE:{whitespaceCharacter= , matchBehavior=contains}", getDetail(validate, 5));
}
@Test
public void givenSourceRule_whenValidatePassword_thenFoundIllegalWordsFromSource() {
SourceRule sourceRule = new SourceRule();
PasswordData passwordData = new PasswordData("password");
passwordData.setPasswordReferences(new PasswordData.SourceReference("source", "password"));
PasswordValidator passwordValidator = new PasswordValidator(sourceRule);
RuleResult validate = passwordValidator.validate(passwordData);
assertFalse(validate.isValid());
assertEquals("SOURCE_VIOLATION:{source=source}", getDetail(validate, 0));
}
@Test
public void givenRepeatCharacterRegexRuleRule_whenValidatePassword_thenFoundIllegalPatternMatches() {
RepeatCharacterRegexRule repeatCharacterRegexRule = new RepeatCharacterRegexRule(3);
PasswordValidator passwordValidator = new PasswordValidator(repeatCharacterRegexRule);
RuleResult validate = passwordValidator.validate(new PasswordData("aaabbb"));
assertFalse(validate.isValid());
assertEquals("ILLEGAL_MATCH:{match=aaa, pattern=([^\\x00-\\x1F])\\1{2}}", getDetail(validate, 0));
assertEquals("ILLEGAL_MATCH:{match=bbb, pattern=([^\\x00-\\x1F])\\1{2}}", getDetail(validate, 1));
}
@Test
public void givenUserNameRule_whenValidatePassword_thenFoundUserNameInPassword() {
PasswordValidator passwordValidator = new PasswordValidator(new UsernameRule());
PasswordData passwordData = new PasswordData("testuser1234");
passwordData.setUsername("testuser");
RuleResult validate = passwordValidator.validate(passwordData);
assertFalse(validate.isValid());
assertEquals("ILLEGAL_USERNAME:{username=testuser, matchBehavior=contains}", getDetail(validate, 0));
}
@Test
public void givenPasswordAndHashBeanAndEncryptedReferences_whenValidate_thenPasswordValidationShouldPass() {
List<PasswordData.Reference> historicalReferences = Arrays.asList(new PasswordData.HistoricalReference("SHA256", "2e4551de804e27aacf20f9df5be3e8cd384ed64488b21ab079fb58e8c90068ab"));
PasswordData passwordData = new PasswordData("example!");
passwordData.setPasswordReferences(historicalReferences);
EncodingHashBean encodingHashBean = new EncodingHashBean(new CodecSpec("Base64"), new DigestSpec("SHA256"), 1, false);
PasswordValidator passwordValidator = new PasswordValidator(new DigestHistoryRule(encodingHashBean));
RuleResult validate = passwordValidator.validate(passwordData);
Assert.assertTrue(validate.isValid());
}
private String getDetail(RuleResult validate, int i) {
return validate.getDetails()
.get(i)
.toString();
}
}

View File

@ -0,0 +1,50 @@
package com.baeldung.passay;
import org.junit.Assert;
import org.junit.Test;
import org.passay.CharacterData;
import org.passay.CharacterRule;
import org.passay.EnglishCharacterData;
import org.passay.PasswordGenerator;
import java.util.stream.Stream;
public class PasswordGeneratorUnitTest {
@Test
public void givenDigitsGenerator_whenGeneratingPassword_thenPasswordContainsDigitsHasLength10() {
CharacterRule digits = new CharacterRule(EnglishCharacterData.Digit);
PasswordGenerator passwordGenerator = new PasswordGenerator();
String password = passwordGenerator.generatePassword(10, digits);
Assert.assertTrue(password.length() == 10);
Assert.assertTrue(containsOnlyCharactersFromSet(password, "0123456789"));
}
@Test
public void givenCustomizedRule_whenGenerating_thenGeneratedPasswordContainsCustomizedCharacters() {
CharacterRule specialCharacterRule = new CharacterRule(new CharacterData() {
@Override
public String getErrorCode() {
return "SAMPLE_ERROR_CODE";
}
@Override
public String getCharacters() {
return "ABCxyz123!@#";
}
});
PasswordGenerator passwordGenerator = new PasswordGenerator();
String password = passwordGenerator.generatePassword(10, specialCharacterRule);
Assert.assertTrue(containsOnlyCharactersFromSet(password, "ABCxyz123!@#"));
}
private boolean containsOnlyCharactersFromSet(String password, String setOfCharacters) {
return Stream.of(password.split(""))
.allMatch(it -> setOfCharacters.contains(it));
}
}

View File

@ -0,0 +1,81 @@
package com.baeldung.passay;
import org.junit.Assert;
import org.junit.Test;
import org.passay.LengthRule;
import org.passay.MessageResolver;
import org.passay.PasswordData;
import org.passay.PasswordValidator;
import org.passay.PropertiesMessageResolver;
import org.passay.RuleResult;
import org.passay.RuleResultDetail;
import org.passay.RuleResultMetadata;
import org.passay.WhitespaceRule;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Properties;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
public class PasswordValidatorUnitTest {
@Test
public void givenPasswordValidatorWithLengthRule_whenValidation_thenTooShortPassword() {
PasswordData passwordData = new PasswordData("1234");
PasswordValidator passwordValidator = new PasswordValidator(new LengthRule(5));
RuleResult validate = passwordValidator.validate(passwordData);
assertEquals(false, validate.isValid());
RuleResultDetail ruleResultDetail = validate.getDetails()
.get(0);
assertEquals("TOO_SHORT", ruleResultDetail.getErrorCode());
assertEquals(5, ruleResultDetail.getParameters()
.get("minimumLength"));
assertEquals(5, ruleResultDetail.getParameters()
.get("maximumLength"));
Integer lengthCount = validate.getMetadata()
.getCounts()
.get(RuleResultMetadata.CountCategory.Length);
assertEquals(Integer.valueOf(4), lengthCount);
}
@Test
public void givenPasswordValidatorWithLengthRule_whenValidation_thenTooLongPassword() {
PasswordData passwordData = new PasswordData("123456");
PasswordValidator passwordValidator = new PasswordValidator(new LengthRule(5));
RuleResult validate = passwordValidator.validate(passwordData);
assertFalse(validate.isValid());
Assert.assertEquals("TOO_LONG", validate.getDetails()
.get(0)
.getErrorCode());
}
@Test
public void givenPasswordValidatorWithLengthRule_whenValidation_thenCustomizedMeesagesAvailable() throws IOException {
URL resource = this.getClass()
.getClassLoader()
.getResource("messages.properties");
Properties props = new Properties();
props.load(new FileInputStream(resource.getPath()));
MessageResolver resolver = new PropertiesMessageResolver(props);
PasswordValidator validator = new PasswordValidator(resolver, new LengthRule(8, 16), new WhitespaceRule());
RuleResult tooShort = validator.validate(new PasswordData("XXXX"));
RuleResult tooLong = validator.validate(new PasswordData("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"));
assertEquals("Password must not contain less characters than 16.", validator.getMessages(tooShort)
.get(0));
assertEquals("Password must not have more characters than 16.", validator.getMessages(tooLong)
.get(0));
}
}

View File

@ -0,0 +1,76 @@
package com.baeldung.passay;
import org.junit.Test;
import org.passay.AllowedCharacterRule;
import org.passay.AllowedRegexRule;
import org.passay.CharacterCharacteristicsRule;
import org.passay.CharacterRule;
import org.passay.EnglishCharacterData;
import org.passay.LengthComplexityRule;
import org.passay.LengthRule;
import org.passay.PasswordData;
import org.passay.PasswordValidator;
import org.passay.RuleResult;
import static org.junit.Assert.*;
public class PositiveMatchingRulesUnitTest {
@Test
public void givenPasswordValidationRules_whenValidatingPassword_thenPosswordIsNotValidWithSeveralErrors() {
PasswordValidator passwordValidator = new PasswordValidator(new AllowedCharacterRule(new char[] { 'a', 'b', 'c' }), new AllowedRegexRule("\\d{2}\\w{10}"), new CharacterRule(EnglishCharacterData.LowerCase, 5), new LengthRule(8, 10));
RuleResult validate = passwordValidator.validate(new PasswordData("12abc"));
assertFalse(validate.isValid());
assertEquals("ALLOWED_CHAR:{illegalCharacter=1, matchBehavior=contains}", getDetail(validate, 0));
assertEquals("ALLOWED_CHAR:{illegalCharacter=2, matchBehavior=contains}", getDetail(validate, 1));
assertEquals("ALLOWED_MATCH:{pattern=\\d{2}\\w{10}}", getDetail(validate, 2));
assertEquals("INSUFFICIENT_LOWERCASE:{" + "minimumRequired=5, matchingCharacterCount=3, " + "validCharacters=abcdefghijklmnopqrstuvwxyz, " + "matchingCharacters=abc}", getDetail(validate, 3));
assertEquals("TOO_SHORT:{minimumLength=8, maximumLength=10}", getDetail(validate, 4));
}
@Test
public void givenRulesForDifferentPasswordLength_whenValidatingTwoDifferentPassword_thenBothOfThemAreInvalid() {
PasswordData shortPassword = new PasswordData("12ab");
PasswordData longPassword = new PasswordData("1234abcde");
LengthComplexityRule lengthComplexityRule = new LengthComplexityRule();
lengthComplexityRule.addRules("[1,5]", new CharacterRule(EnglishCharacterData.LowerCase, 5));
lengthComplexityRule.addRules("[6,10]", new AllowedCharacterRule(new char[] { 'a', 'b', 'c', 'd' }));
PasswordValidator passwordValidator = new PasswordValidator(lengthComplexityRule);
RuleResult validateShort = passwordValidator.validate(shortPassword);
RuleResult validateLong = passwordValidator.validate(longPassword);
assertFalse(validateShort.isValid());
assertFalse(validateLong.isValid());
assertEquals("INSUFFICIENT_LOWERCASE:{" + "minimumRequired=5, " + "matchingCharacterCount=2, " + "validCharacters=abcdefghijklmnopqrstuvwxyz, " + "matchingCharacters=ab}", getDetail(validateShort, 0));
assertEquals("ALLOWED_CHAR:{illegalCharacter=1, matchBehavior=contains}", getDetail(validateLong, 0));
}
@Test
public void givenCharacterCharacteristicsRule_whenValidatingPassword_thenItIsInvalidAsItBreaksToManyRules() {
PasswordData shortPassword = new PasswordData();
shortPassword.setPassword("12345abcde!");
CharacterCharacteristicsRule characterCharacteristicsRule = new CharacterCharacteristicsRule(4, new CharacterRule(EnglishCharacterData.LowerCase, 5), new CharacterRule(EnglishCharacterData.UpperCase, 5), new CharacterRule(EnglishCharacterData.Digit),
new CharacterRule(EnglishCharacterData.Special));
PasswordValidator passwordValidator = new PasswordValidator(characterCharacteristicsRule);
RuleResult validate = passwordValidator.validate(shortPassword);
assertFalse(validate.isValid());
assertEquals("INSUFFICIENT_UPPERCASE:{" + "minimumRequired=5, " + "matchingCharacterCount=0, " + "validCharacters=ABCDEFGHIJKLMNOPQRSTUVWXYZ, " + "matchingCharacters=}", getDetail(validate, 0));
assertEquals("INSUFFICIENT_CHARACTERISTICS:{" + "successCount=3, " + "minimumRequired=4, " + "ruleCount=4}", getDetail(validate, 1));
}
private String getDetail(RuleResult validate, int i) {
return validate.getDetails()
.get(i)
.toString();
}
}

View File

@ -0,0 +1,2 @@
TOO_LONG=Password must not have more characters than %2$s.
TOO_SHORT=Password must not contain less characters than %2$s.