Passayへのガイド

Passayへのガイド

1. 前書き

最近では、ほとんどのWebアプリケーションにはパスワードポリシーがあります。これは、簡単に言えば、ユーザーに破られにくいパスワードの作成を強制するために作成されたものです。

このようなパスワードを生成または検証するには、Passay libraryを使用できます。

2. メーベン依存

プロジェクトでPassayライブラリを使用する場合は、pom.xmlに次の依存関係を追加する必要があります。


    org.passay
    passay
    1.3.1

hereで見つけることができます。

3. パスワード検証

パスワード検証は、Passayライブラリーが提供する2つの主要機能の1つです。 簡単で直感的です。 それを発見しましょう。

3.1. PasswordData

パスワードを検証するには、PasswordData.It’s a container for information that is necessary for validation.を使用する必要があります。次のようなデータを保存できます。

  • パスワード

  • ユーザー名

  • パスワード参照のリスト

  • 原点

パスワードとユーザー名のプロパティについて説明します。 Passayライブラリは、パスワード参照のリストに追加できるHistoricalReferenceSourceReferenceを提供します。

originフィールドを使用して、パスワードがユーザーによって生成または定義されたかどうかに関する情報を保持できます。

3.2. PasswordValidator

We should know that we need PasswordData and PasswordValidator objects to start validating passwords. PasswordDataについてはすでに説明しました。 PasswordValidatorを作成しましょう。

まず、パスワード検証の一連のルールを定義する必要があります。 PasswordValidatorオブジェクトを作成するときに、それらをコンストラクターに渡す必要があります。

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

パスワードをPasswordDataオブジェクトに渡す方法は2つあります。 これをコンストラクターまたはセッターメソッドに渡します。

PasswordData passwordData = new PasswordData("1234");

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

PasswordValidatorvalidate()メソッドを呼び出すことにより、パスワードを検証できます。

RuleResult validate = passwordValidator.validate(passwordData);

その結果、RuleResultオブジェクトを取得します。

3.3. RuleResult

RuleResultは、検証プロセスに関する興味深い情報を保持しています。 これは、validate()メソッドの結果として発生します。

まず、パスワードが有効かどうかを確認できます。

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

Moreover, we can learn what errors are returned when the password is invalid.エラーコードと検証の説明はRuleResultDetailに保持されます。

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

最後に、RuleResultMetadataを使用してパスワード検証のメタデータを調べることができます。

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

4. パスワード生成

検証に加えて、Passayライブラリを使用してパスワードを生成できます。 We can provide rules which the generator should use.

パスワードを生成するには、PasswordGeneratorオブジェクトが必要です。 取得したら、generatePassword()メソッドを呼び出し、CharacterRulesのリストを渡します。 これがサンプルコードです。

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

CharacterRuleを作成するには、CharacterDataのオブジェクトが必要であることを知っておく必要があります。 Another interesting fact is that the library provides us with EnglishCharacterData.これは5セットの文字の列挙型です。

  • 小文字の英語アルファベット

  • 大文字の英語のアルファベット

  • 小文字と大文字のセットの組み合わせ

  • 特殊文字

However, nothing can stop us from defining our set of characters.CharacterDataインターフェースを実装するのと同じくらい簡単です。 どうすればよいか見てみましょう。

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. ポジティブマッチングルール

パスワードを生成して検証する方法については、すでに学習しました。 そのためには、一連のルールを定義する必要があります。 For that reason, we should know that there are two types of rules available in Passay: positive matching rules and negative matching rules.

まず、ポジティブルールとは何か、そしてそれらをどのように使用できるかを見てみましょう。

ポジティブマッチングルールは、指定された文字、正規表現を含むパスワード、またはいくつかの制限に適合するパスワードを受け入れます。

6つの正のマッチングルールがあります。

  • AllowedCharacterRule –パスワードに含める必要のあるすべての文字を定義します

  • AllowedRegexRule –パスワードが一致する必要がある正規表現を定義します

  • CharacterRule –パスワードに含める必要のある文字セットと最小文字数を定義します

  • LengthRule –パスワードの最小の長さを定義します

  • CharacterCharacteristicsRule –パスワードが定義されたルールのNを満たしているかどうかを確認します。

  • LengthComplexityRule –パスワードの長さごとに異なるルールを定義できます

5.1. 単純なポジティブマッチングルール

次に、単純な構成を持つすべてのルールについて説明します。 They define a set of legal characters or patterns or an acceptable password’s length.

議論されたルールの短い例を次に示します。

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.パスワードが短すぎて、2つの不正な文字が含まれているという通知があります。 また、パスワードが提供された正規表現と一致しないこともわかります。

さらに、小文字が不十分であることが通知されます。

5.2. CharacterCharacterisitcsRule

CharcterCharacterisitcsRuleは、前に示したルールよりも複雑です。 To create a CharcterCharacterisitcsRule object, we need to provide a list of CharacterRules.さらに、パスワードが一致する必要があるものの数を設定する必要があります。 次のようにできます。

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

提示されたCharacterCharacteristicsRuleには、提供された4つのルールのうち3つを含むパスワードが必要です。

5.3. LengthComplexityRule

一方、PassayライブラリはLengthComplexityRuleを提供します。 It allows us to define which rules should be applied to the password of which length.CharacterCharacteristicsRuleとは対照的に、CharacterRuleだけでなく、あらゆる種類のルールを使用できます。

例を分析してみましょう。

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

1〜5文字のパスワードでわかるように、CharacterRuleを適用します。 ただし、6〜10文字を含むパスワードの場合、パスワードをAllowedCharacterRuleと一致させる必要があります。

6. ネガティブマッチングルール

ポジティブマッチングルールとは異なり、ネガティブマッチングルールは、提供された文字、正規表現、エントリなどを含むパスワードを拒否します。

ネガティブマッチングルールとは何かを調べてみましょう。

  • IllegalCharacterRule –パスワードに含めることのできないすべての文字を定義します

  • IllegalRegexRule –一致してはならない正規表現を定義します

  • IllegalSequenceRule –パスワードに不正な文字シーケンスが含まれていないかどうかを確認します

  • NumberRangeRule –パスワードに含めてはならない数値の範囲を定義します

  • WhitespaceRule –パスワードに空白が含まれているかどうかを確認します

  • DictionaryRule –パスワードが辞書レコードと等しいかどうかを確認します

  • DictionarySubstringRule –パスワードに辞書レコードが含まれているかどうかを確認します

  • HistoryRule –パスワードに過去のパスワード参照が含まれているかどうかを確認します

  • DigestHistoryRule –パスワードにダイジェストされた過去のパスワード参照が含まれているかどうかを確認します

  • SourceRule –パスワードにソースパスワード参照が含まれているかどうかを確認します

  • DigestSourceRule –パスワードにダイジェストソースパスワード参照が含まれているかどうかを確認します

  • UsernameRule –パスワードにユーザー名が含まれているかどうかを確認します

  • RepeatCharacterRegexRule –パスワードに繰り返しASCII文字が含まれているかどうかを確認します

6.1. 単純なネガティブマッチングルール

まず、IllegalCharacterRuleIllegalRegexRuleなどの単純なルールをどのように使用できるかを見ていきます。 これは簡単な例です。

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

この例は、説明されているルールがどのように機能するかを示しています。 ポジティブマッチングルールと同様に、検証に関する完全なフィードバックを提供します。

6.2. 辞書ルール

パスワードが指定された単語と等しくないかどうかを確認する場合はどうなりますか。

そのため、Passayライブラリはそのための優れたツールを提供します。 DictionaryRuleDictionarySubstringRuleを見つけましょう:

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.最も一般的または最も簡単に解読できるパスワードのリストがあると便利です。 したがって、ユーザーによる使用を禁止することは合理的です。

実際には、テキストファイルまたはデータベースから単語のリストを確実にロードします。 その場合、WordListsを使用できます。 Readersの配列を受け取り、ArrayWordListを作成する3つのオーバーロードされたメソッドがあります。

6.3. HistoryRuleおよびSourceRule

さらに、PassayライブラリはHistoryRuleSourceRuleを提供します。 さまざまなソースからの履歴パスワードまたはテキストコンテンツに対してパスワードを検証できます。

例を見てみましょう:

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は、パスワードが以前に使用されたことがあるかどうかを確認するのに役立ちます。 このような方法は安全ではないため、ユーザーに古いパスワードを使用させたくありません。

一方、SourceRuleを使用すると、パスワードがSourceReferencesで提供されているものと異なるかどうかを確認できます。 異なるシステムまたはアプリケーションで同じパスワードを使用するリスクを回避できます。

DigestSourceRuleDigestHistoryRule.などのルールがあることは言及する価値があります。これらについては、次の段落で説明します。

6.4. ダイジェストルール

Passayライブラリには、DigestHistoryRuleDigestSourceRuleの2つのダイジェストルールがあります。 Digest rules are intended to work with passwords stored as digest or hash.したがって、それらを定義するには、EncodingHashBeanオブジェクトを提供する必要があります。

それがどのように行われるか見てみましょう:

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

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

今回は、ラベルとコンストラクターへのエンコードされたパスワードによってHistoricalReferenceを作成します。 その後、適切なコーデックとダイジェストアルゴリズムを使用してEncodingHashBeanをインスタンス化しました。

さらに、反復回数とアルゴリズムにソルトを適用するかどうかを指定できます。

エンコーディングBeanを取得したら、ダイジェストパスワードを検証できます。

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

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

RuleResult validate = passwordValidator.validate(passwordData);

Assert.assertTrue(validate.isValid());

Cryptacular library webpageEncodingHashinBeanについて詳しく知ることができます。

6.5. RepeatCharacterRegexRule

もう1つの興味深い検証ルールはRepeatCharacterRegexRuleです。 We can use it to check whether password contains repeating ASCII characters.

サンプルコードは次のとおりです。

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

この章で説明する最後のルールはUsernameRuleです。 It enables us to prohibit using the user’s name in the password. 

以前に学習したように、ユーザー名をPasswordDataに保存する必要があります。

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. カスタマイズされたメッセージ

Passayライブラリを使用すると、検証ルールによって返されるメッセージをカスタマイズできます。 Firstly, we should define the messages and assign them to error codes.

それらを単純なファイルに入れることができます。 それがいかに簡単か見てみましょう:

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

メッセージを取得したら、そのファイルをロードする必要があります。 最後に、それをPasswordValidatorオブジェクトに渡すことができます。

これがサンプルコードです。

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

MessageResolver resolver = new PropertiesMessageResolver(props);

ご覧のとおり、message.propertiesファイルをロードして、Propertiesオブジェクトに渡しました。 次に、Propertiesオブジェクトを使用してPropertiesMessageResolverを作成できます。

メッセージリゾルバの使用方法の例を見てみましょう。

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

この例は、メッセージリゾルバーを備えたバリデーターを使用してすべてのエラーコードを変換できることを明確に示しています。

8. 結論

このチュートリアルでは、Passayライブラリの使用方法を学習しました。 ライブラリをパスワード検証に簡単に使用する方法の例をいくつか分析しました。 規定された規則は、パスワードが安全であることを保証する一般的な方法のほとんどをカバーしています。

ただし、Passayライブラリ自体はパスワードを安全にしないことを覚えておく必要があります。 まず、一般的なルールとは何かを学習し、ライブラリを使用してそれらを実装する必要があります。

すべての例は、いつものように、over on GitHubで見つけることができます。