Guide to Passay

Führer zu Passay

1. Einführung

Heutzutage haben die meisten Webanwendungen eine Kennwortrichtlinie - die einfach ausgedrückt erstellt wird, um Benutzer dazu zu zwingen, schwer zu knackende Kennwörter zu erstellen.

Um solche Passwörter zu generieren oder zu validieren, können wirPassay library verwenden.

2. Maven-Abhängigkeit

Wenn wir die Passay-Bibliothek in unserem Projekt verwenden möchten, müssen Sie unserenpom.xml die folgende Abhängigkeit hinzufügen:


    org.passay
    passay
    1.3.1

Wir können eshere finden.

3. Passwortüberprüfung

Die Kennwortüberprüfung ist eine der beiden Hauptfunktionen der Passay-Bibliothek. Es ist mühelos und intuitiv. Lass es uns entdecken.

3.1. PasswordData

Um unser Passwort zu validieren, sollten wirPasswordData.It’s a container for information that is necessary for validation. verwenden. Es kann folgende Daten speichern:

  • Passwort

  • Nutzername

  • Liste der Passwortreferenzen

  • Ursprung

Die Eigenschaften von Passwort und Benutzername erklären sich von selbst. Die Passay-Bibliothek gibt unsHistoricalReference undSourceReference, die wir der Liste der Passwortreferenzen hinzufügen können.

Wir können das Ursprungsfeld verwenden, um Informationen darüber zu speichern, ob das Kennwort von einem Benutzer generiert oder definiert wurde.

3.2. PasswordValidator

We should know that we need PasswordData and PasswordValidator objects to start validating passwords. Wir haben bereitsPasswordData besprochen. Erstellen wir jetztPasswordValidator.

Erstens sollten wir einen Satz von Regeln für die Kennwortüberprüfung definieren. Wir müssen sie an den Konstruktor übergeben, während wir einPasswordValidator-Objekt erstellen:

PasswordValidator passwordValidator = new PasswordValidator(new LengthRule(5));

Es gibt zwei Möglichkeiten, unser Passwort an das ObjektPasswordDatazu übergeben. Wir übergeben es entweder an den Konstruktor oder an die Setter-Methode:

PasswordData passwordData = new PasswordData("1234");

PasswordData passwordData2 = new PasswordData();
passwordData.setPassword("1234");

Wir können unser Passwort überprüfen, indem wir die Methodevalidate()fürPasswordValidator aufrufen:

RuleResult validate = passwordValidator.validate(passwordData);

Als Ergebnis erhalten wir einRuleResult-Objekt.

3.3. RuleResult

RuleResult enthält interessante Informationen über einen Validierungsprozess. Dies ergibt sich aus der Methodevalidate().

Zunächst kann es uns sagen, ob das Passwort gültig ist:

Assert.assertEquals(false, validate.isValid());

Moreover, we can learn what errors are returned when the password is invalid. Fehlercodes und Validierungsbeschreibungen werden inRuleResultDetail gespeichert:

RuleResultDetail ruleResultDetail = validate.getDetails().get(0);
Assert.assertEquals("TOO_SHORT", ruleResultDetail.getErrorCode());
Assert.assertEquals(5, ruleResultDetail.getParameters().get("minimumLength"));
Assert.assertEquals(5, ruleResultDetail.getParameters().get("maximumLength"));

Schließlich können wir die Metadaten der Passwortüberprüfung mitRuleResultMetadata untersuchen:

Integer lengthCount = validate
  .getMetadata()
  .getCounts()
  .get(RuleResultMetadata.CountCategory.Length);
Assert.assertEquals(Integer.valueOf(4), lengthCount);

4. Passwort-Generierung

Zusätzlich zur Validierung können wir mit derPassay-Bibliothek Kennwörter generieren. We can provide rules which the generator should use.

Um ein Passwort zu generieren, benötigen wir einPasswordGenerator-Objekt. Sobald wir es haben, rufen wir die MethodegeneratePassword() auf und übergeben die Liste vonCharacterRules. Hier ist ein Beispielcode:

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"));

Wir sollten wissen, dass wir ein Objekt vonCharacterData benötigen, umCharacterRule zu erstellen. Another interesting fact is that the library provides us with EnglishCharacterData. Es handelt sich um eine Aufzählung von fünf Zeichensätzen:

  • Ziffern

  • Englisches Alphabet in Kleinbuchstaben

  • englisches Alphabet in Großbuchstaben

  • Kombination von Klein- und Großbuchstaben

  • spezielle Charaktere

However, nothing can stop us from defining our set of characters. Es ist so einfach wie die Implementierung derCharacterData-Schnittstelle. Mal sehen, wie wir das machen können:

CharacterRule specialCharacterRule = new CharacterRule(new CharacterData() {
    @Override
    public String getErrorCode() {
        return "SAMPLE_ERROR_CODE";
    }

    @Override
    public String getCharacters() {
        return "[email protected]#";
    }
});

PasswordGenerator passwordGenerator = new PasswordGenerator();
String password = passwordGenerator.generatePassword(10, specialCharacterRule);

Assert.assertTrue(containsOnlyCharactersFromSet(password, "[email protected]#"));

5. Positive Übereinstimmungsregeln

Wir haben bereits gelernt, wie wir Passwörter generieren und validieren können. Dazu müssen wir eine Reihe von Regeln definieren. For that reason, we should know that there are two types of rules available in Passay: positive matching rules and negative matching rules.

Lassen Sie uns zunächst herausfinden, welche positiven Regeln gelten und wie wir sie anwenden können.

Positive Übereinstimmungsregeln akzeptieren Kennwörter, die bereitgestellte Zeichen, reguläre Ausdrücke enthalten oder einigen Einschränkungen entsprechen.

Es gibt sechs Regeln für positive Übereinstimmungen:

  • AllowedCharacterRule - definiert alle Zeichen, die das Passwort enthalten muss

  • AllowedRegexRule - definiert einen regulären Ausdruck, mit dem das Passwort übereinstimmen muss

  • CharacterRule - Definiert einen Zeichensatz und eine minimale Anzahl von Zeichen, die im Kennwort enthalten sein sollen

  • LengthRule - Definiert eine minimale Länge des Passworts

  • CharacterCharacteristicsRule - prüft, ob das PasswortN der definierten Regeln erfüllt.

  • LengthComplexityRule - ermöglicht es uns, verschiedene Regeln für verschiedene Passwortlängen zu definieren

5.1. Einfache Regeln für positive Übereinstimmungen

Jetzt werden wir alle Regeln behandeln, die eine einfache Konfiguration haben. They define a set of legal characters or patterns or an acceptable password’s length.

Hier ist ein kurzes Beispiel für die diskutierten Regeln:

PasswordValidator passwordValidator = new PasswordValidator(
  new AllowedCharacterRule(new char[] { 'a', 'b', 'c' }),
  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(
  "TOO_SHORT:{minimumLength=8, maximumLength=10}",
  getDetail(validate, 4));

We can see that each rule gives us a clear explanation if the password is not valid. Es gibt Benachrichtigungen, dass das Passwort zu kurz ist und zwei unzulässige Zeichen enthält. Wir können auch feststellen, dass das Passwort nicht mit dem angegebenen regulären Ausdruck übereinstimmt.

Darüber hinaus werden wir darüber informiert, dass es nicht genügend Kleinbuchstaben enthält.

5.2. CharacterCharacterisitcsRule

CharcterCharacterisitcsRule ist komplexer als die zuvor vorgestellten Regeln. To create a CharcterCharacterisitcsRule object, we need to provide a list of CharacterRules. Außerdem müssen wir festlegen, mit wie vielen von ihnen das Passwort übereinstimmen muss. Wir können es so machen:

CharacterCharacteristicsRule characterCharacteristicsRule = new CharacterCharacteristicsRule(
  3,
  new CharacterRule(EnglishCharacterData.LowerCase, 5),
  new CharacterRule(EnglishCharacterData.UpperCase, 5),
  new CharacterRule(EnglishCharacterData.Digit),
  new CharacterRule(EnglishCharacterData.Special)
);

Für PresentedCharacterCharacteristicsRule ist ein Kennwort erforderlich, das drei von vier bereitgestellten Regeln enthält.

5.3. LengthComplexityRule

Andererseits liefert uns die Bibliothek vonPassayLengthComplexityRule. It allows us to define which rules should be applied to the password of which length. Im Gegensatz zuCharacterCharacteristicsRule können wir alle Arten von Regeln verwenden - nicht nurCharacterRule.

Analysieren wir das Beispiel:

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' }));

Wie wir für ein Passwort mit ein bis fünf Zeichen sehen können, wenden wirCharacterRule an. Für ein Passwort mit sechs bis zehn Zeichen soll das Passwort jedoch mitAllowedCharacterRule übereinstimmen.

6. Negative Übereinstimmungsregeln

Im Gegensatz zu positiven Übereinstimmungsregeln lehnen negative Übereinstimmungsregeln Kennwörter ab, die bereitgestellte Zeichen, reguläre Ausdrücke, Einträge usw. enthalten.

Lassen Sie uns herausfinden, welche negativen Übereinstimmungsregeln gelten:

  • IllegalCharacterRule - Definiert alle Zeichen, die ein Passwort nicht enthalten darf

  • IllegalRegexRule - definiert einen regulären Ausdruck, der nicht übereinstimmen darf

  • IllegalSequenceRule - prüft, ob ein Passwort eine unzulässige Zeichenfolge enthält

  • NumberRangeRule - Definiert einen Zahlenbereich, den ein Passwort nicht enthalten darf

  • WhitespaceRule - prüft, ob ein Passwort Leerzeichen enthält

  • DictionaryRule - Überprüft, ob ein Kennwort einem Wörterbuchdatensatz entspricht

  • DictionarySubstringRule - Überprüft, ob ein Kennwort einen Wörterbucheintrag enthält

  • HistoryRule - prüft, ob ein Passwort eine historische Passwortreferenz enthält

  • DigestHistoryRule - Überprüft, ob ein Kennwort eine verdaute historische Kennwortreferenz enthält

  • SourceRule - prüft, ob ein Kennwort eine Quellkennwortreferenz enthält

  • DigestSourceRule - Überprüft, ob ein Kennwort eine Kennwortreferenz für die Digest-Quelle enthält

  • UsernameRule - prüft, ob ein Passwort einen Benutzernamen enthält

  • RepeatCharacterRegexRule - prüft, ob ein Passwort wiederholteASCII-Zeichen enthält

6.1. Einfache ausschließende Übereinstimmungsregeln

Zunächst werden wir sehen, wie wir einfache Regeln wieIllegalCharacterRule,IllegalRegexRule usw. verwenden können. Hier ist ein kurzes Beispiel:

PasswordValidator passwordValidator = new PasswordValidator(
  new IllegalCharacterRule(new char[] { 'a' }),
  new NumberRangeRule(1, 10),
  new WhitespaceRule()
);

RuleResult validate = passwordValidator.validate(new PasswordData("abcd22 "));

assertFalse(validate.isValid());
assertEquals(
  "ILLEGAL_CHAR:{illegalCharacter=a, matchBehavior=contains}",
  getDetail(validate, 0));
assertEquals(
  "ILLEGAL_NUMBER_RANGE:{number=2, matchBehavior=contains}",
  getDetail(validate, 4));
assertEquals(
  "ILLEGAL_WHITESPACE:{whitespaceCharacter= , matchBehavior=contains}",
  getDetail(validate, 5));

Das Beispiel zeigt uns, wie die beschriebenen Regeln funktionieren. Ähnlich wie bei positiven Übereinstimmungsregeln geben sie uns ein vollständiges Feedback zur Validierung.

6.2. Wörterbuchregeln

Was ist, wenn wir überprüfen möchten, ob ein Passwort nicht mit den angegebenen Wörtern übereinstimmt?

Aus diesem Grund bietet uns die BibliothekPassayhervorragende Werkzeuge dafür. Entdecken wirDictionaryRule undDictionarySubstringRule:

WordListDictionary wordListDictionary = new WordListDictionary(
  new ArrayWordList(new String[] { "bar", "foobar" }));

DictionaryRule dictionaryRule = new DictionaryRule(wordListDictionary);
DictionarySubstringRule dictionarySubstringRule = new DictionarySubstringRule(wordListDictionary);

We can see dictionary rules enable us to provide a list of banned words. Es ist von Vorteil, wenn wir eine Liste der am häufigsten oder am einfachsten zu knackenden Passwörter haben. Daher ist es sinnvoll, Benutzern die Verwendung zu untersagen.

Im wirklichen Leben würden wir sicherlich eine Liste von Wörtern aus einer Textdatei oder einer Datenbank laden. In diesem Fall können wirWordLists verwenden. Es gibt drei überladene Methoden, die ein Array vonReaders verwenden undArrayWordList erstellen.

6.3. HistoryRule undSourceRule

Darüber hinaus gibt die BibliothekPassayHistoryRule undSourceRule an. Sie können Kennwörter anhand von historischen Kennwörtern oder Textinhalten aus verschiedenen Quellen validieren.

Schauen wir uns das Beispiel an:

SourceRule sourceRule = new SourceRule();
HistoryRule historyRule = new HistoryRule();

PasswordData passwordData = new PasswordData("123");
passwordData.setPasswordReferences(
  new PasswordData.SourceReference("source", "password"),
  new PasswordData.HistoricalReference("12345")
);

PasswordValidator passwordValidator = new PasswordValidator(
  historyRule, sourceRule);

HistoryRules helfen uns zu überprüfen, ob zuvor ein Passwort verwendet wurde. Da solche Praktiken unsicher sind, möchten wir nicht, dass Benutzer alte Kennwörter verwenden.

Andererseits können wir mitSourceRule prüfen, ob sich das Kennwort von dem inSourceReferences angegebenen unterscheidet. Wir können das Risiko vermeiden, dass in verschiedenen Systemen oder Anwendungen dieselben Passwörter verwendet werden.

Es ist erwähnenswert, dass es Regeln wieDigestSourceRule undDigestHistoryRule. gibt. Wir werden sie im nächsten Absatz behandeln.

6.4. Digest-Regeln

In derPassay-Bibliothek gibt es zwei Digest-Regeln:DigestHistoryRule undDigestSourceRule. Digest rules are intended to work with passwords stored as digest or hash. Um sie zu definieren, müssen wir daher einEncodingHashBean-Objekt bereitstellen.

Mal sehen, wie es geht:

List historicalReferences = Arrays.asList(
  new PasswordData.HistoricalReference(
    "SHA256",
    "2e4551de804e27aacf20f9df5be3e8cd384ed64488b21ab079fb58e8c90068ab"
));

EncodingHashBean encodingHashBean = new EncodingHashBean(
  new CodecSpec("Base64"),
  new DigestSpec("SHA256"),
  1,
  false
);

Dieses Mal erstellen wirHistoricalReference mit einem Label und dem codierten Passwort für den Konstruktor. Danach haben wirEncodingHashBean mit dem richtigen Codec- und Digest-Algorithmus instanziiert.

Zusätzlich können wir die Anzahl der Iterationen angeben und festlegen, ob der Algorithmus gesalzen wird.

Sobald wir eine Kodierungs-Bean haben, können wir unser Digest-Passwort validieren:

PasswordData passwordData = new PasswordData("example!");
passwordData.setPasswordReferences(historicalReferences);

PasswordValidator passwordValidator = new PasswordValidator(new DigestHistoryRule(encodingHashBean));

RuleResult validate = passwordValidator.validate(passwordData);

Assert.assertTrue(validate.isValid());

Wir können mehr überEncodingHashinBean beiCryptacular library webpage erfahren.

6.5. RepeatCharacterRegexRule

Eine weitere interessante Validierungsregel istRepeatCharacterRegexRule. We can use it to check whether password contains repeating ASCII characters.

Hier ist ein Beispielcode:

PasswordValidator passwordValidator = new PasswordValidator(new RepeatCharacterRegexRule(3));

RuleResult validate = passwordValidator.validate(new PasswordData("aaabbb"));

assertFalse(validate.isValid());
assertEquals("ILLEGAL_MATCH:{match=aaa, pattern=([^\\x00-\\x1F])\\1{2}}", getDetail(validate, 0));

6.6. UsernameRule

Die letzte Regel, die wir in diesem Kapitel diskutieren werden, istUsernameRule. It enables us to prohibit using the user’s name in the password. 

Wie wir zuvor erfahren haben, sollten wir den Benutzernamen inPasswordData speichern:

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));

7. Angepasste Nachrichten

Mit der Bibliothek vonPassaykönnen wir Nachrichten anpassen, die von Validierungsregeln zurückgegeben werden. Firstly, we should define the messages and assign them to error codes.

Wir können sie in eine einfache Datei einfügen. Mal sehen, wie einfach es ist:

TOO_LONG=Password must not have more characters than %2$s.
TOO_SHORT=Password must not contain less characters than %2$s.

Sobald wir Nachrichten haben, müssen wir diese Datei laden. Schließlich können wir es an das Objekt vonPasswordValidatorübergeben.

Hier ist ein Beispielcode:

URL resource = this.getClass().getClassLoader().getResource("messages.properties");
Properties props = new Properties();
props.load(new FileInputStream(resource.getPath()));

MessageResolver resolver = new PropertiesMessageResolver(props);

Wie wir sehen können, haben wir die Dateimessage.propertiesgeladen und an das ObjektPropertiesübergeben. Dann können wir das ObjektProperties verwenden, umPropertiesMessageResolver zu erstellen.

Schauen wir uns das Beispiel zur Verwendung des Nachrichtenauflösers an:

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"));

Assert.assertEquals(
  "Password must not contain less characters than 16.",
  validator.getMessages(tooShort).get(0));
Assert.assertEquals(
  "Password must not have more characters than 16.",
  validator.getMessages(tooLong).get(0));

Das Beispiel zeigt deutlich, dass wir mit dem Validator, der mit einem Message Resolver ausgestattet ist, alle Fehlercodes übersetzen können.

8. Fazit

In diesem Tutorial haben wir gelernt, wie Sie die Bibliothek vonPassayverwenden. Wir haben einige Beispiele analysiert, wie die Bibliothek einfach zur Kennwortüberprüfung verwendet werden kann. Die bereitgestellten Regeln decken die meisten gängigen Methoden ab, um die Sicherheit eines Kennworts zu gewährleisten.

Wir sollten uns jedoch daran erinnern, dass die Passay-Bibliothek selbst unser Passwort nicht sicher macht. Zunächst sollten wir allgemeine Regeln kennenlernen und diese dann mithilfe der Bibliothek implementieren.

Alle Beispiele finden sich wie immer inover on GitHub.