Webアプリケーションを作成していると、
- ユーザが入力したパスワードがポリシーに沿っているか確認する
- アプリケーション側でパスワードを生成してユーザに通知する
といった仕組みが必要になることがあります。
こうしたパスワードに関する面倒な機能を提供してくれるのが、今日紹介するPassayです。
かなり多機能なので、どんなことができるのか解説していきたいと思います。
なお、バージョンは記事を書いた時点(2021年9月12日)の最新である1.6.1を前提にしています。最新版はPassayの公式ページで確認してください。
Passayを利用するための準備
Passayを利用するための方法です。メジャーだと思う3種類を準備しました。
私はMavenを使いますが、この記事で書くソースファイルはどの方法でも動きます。
jarファイル
Passayのjarファイルは公式サイトのダウンロードページにあります。zipファイルかtar.gzファイルをダウンロードして解凍してください。
jarsフォルダのpassay-1.6.1.jarをclasspathに追加すればOKです。
Maven
pom.xmlのdependenciesタグにPassayの情報を追加します。
<dependencies>
<dependency>
<groupId>org.passay</groupId>
<artifactId>passay</artifactId>
<version>1.6.1</version>
</dependency>
</dependencies>
Gradle
build.gradleのdependenciesにPassayの情報を追加します。
dependencies {
implementation 'org.passay:passay:1.6.1'
}
パスワードの検証・チェック
ユーザが入力したパスワードがポリシーに合っているかを確認するための方法です。
とりあえずサンプルコードをお見せします。
private static void checkPassword(String password) {
PasswordValidator validator = new PasswordValidator(
// 長さは8文字から16文字まで
new LengthRule(8, 16),
// 1文字以上の大文字のアルファベットが必須
new CharacterRule(EnglishCharacterData.UpperCase, 1),
// 1文字以上の小文字のアルファベットが必須
new CharacterRule(EnglishCharacterData.LowerCase, 1),
// 1文字以上の数字が必須
new CharacterRule(EnglishCharacterData.Digit, 1),
// 1文字以上の記号が必須
new CharacterRule(EnglishCharacterData.Special, 1),
// 空白やタブはない
new WhitespaceRule());
RuleResult result = validator.validate(new PasswordData(password));
if (result.isValid()) {
System.out.println("妥当なパスワード");
} else {
System.out.println("不当なパスワード:");
for (String msg : validator.getMessages(result)) {
System.out.println(msg);
}
}
}
このメソッドは、引数の文字列が妥当なパスワードなのか検証して、妥当なら「妥当なパスワード」、そうでないなら「不当なパスワード:」と不当な理由を表示します。(このままだと、不当な理由は英語です。後で日本語化する方法を説明します。)
何を持って妥当なのかを判定するために、Passayではorg.passay.Ruleを実装したクラスをPasswordValidatorに渡します。個々のルールの概要はコメントに書いた通りです。
PassayではRuleの理解が必要です。結構な数のRuleクラスがあるので、後で概要を説明します。
ここでは、パスワードの検証を行うためにはPasswordValidatorにRuleを渡してインスタンスを生成し、validateメソッドを使うということだけ理解できればいいでしょう。
メッセージを日本語にする
パスワードが不当な理由を日本語化する方法です。
- エラーメッセージを日本語化したpropertiesファイルを作成する
- Propertiesにロードする
- Propertiesを引数にしてPropertiesMessageResolverを作成する
- PasswordValidatorインスタンスを作成する際にPropertiesMessageResolverを第一引数に渡す
ソースコードにするとこんな感じです。
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.propertiesに必要な項目は以下のファイルの通りです。大変なので日本語訳はしていません・・・。全部を翻訳する必要はないので、利用するRuleに関連するところだけ翻訳して使ってください。
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.
パスワードの生成
パスワードの検証で使ったRuleのうち、CharacterRuleを利用してパスワードの生成ができます。
private static String createPassword() {
List<CharacterRule> rules = Arrays.asList(
// 1文字以上の大文字のアルファベットが必須
new CharacterRule(EnglishCharacterData.UpperCase, 1),
// 1文字以上の小文字のアルファベットが必須
new CharacterRule(EnglishCharacterData.LowerCase, 1),
// 1文字以上の数字が必須
new CharacterRule(EnglishCharacterData.Digit, 1));
PasswordGenerator generator = new PasswordGenerator();
// 上で設定したルールを満たす8文字のパスワードを生成
String password = generator.generatePassword(8, rules);
return password;
}
このメソッドだと、CharacterRuleで指定した文字を利用したランダムな8文字の文字列が生成されます。各CharacterRuleごとに最低1文字は使われる設定です。
パスワード生成に関しては、CharacterRuleの配列を渡してgenerator.generatePasswordを使うことを覚えておけば良いでしょう。
Rule概要
Passayにはたくさんのルールがあります。全部を覚える必要はないので、必要になったら読み返してください。
ポジティブなRule
許容する設定を記述するルールです。
Ruleの名前 | 概要 |
AllowedCharacterRule | 指定したcharの配列だけでパスワードが構成されている |
AllowedRegexRule | 指定した正規表現を満たしている |
CharacterCharacteristicsRule | 複数のCharacterRuleをまとめたRule、その中のいくつを満たせばいいか設定できる |
CharacterRule | 指定したCharacterDataを持っている。最低限必要な文字数も設定できる |
LengthRule | 必要な長さを設定できる |
LengthComplexityRule | パスワードの長さごとに必要なルールを設定できる |
ネガティブなルール
許容しない設定を記述するルールです
Ruleの名前 | 概要 |
DictionaryRule | 特定の文字列が完全一致した場合許容しない |
DictionarySubstringRule | 特定の文字列が部分一致した場合許容しない |
DigestDictionaryRule | 特定の文字列がハッシュ化した上で一致した場合した場合許容しない |
HistoryRule | 以前使われたパスワードを許容しない |
DigestHistoryRule | 以前使われたパスワードをハッシュ化して比較した上で許容しない |
CharacterOccurrencesRule | 同じ文字が指定数以上使われた場合許容しない |
IllegalCharacterRule | 指定した文字を含んでいた場合許容しない |
IllegalRegexRule | 指定した正規表現を満たす場合許容しない |
IllegalSequenceRule | 指定したSequenceDataで連続した場合許容しない(例えば12345など) |
NumberRangeRule | 指定した範囲の数字を含んでいた場合許容しない |
SourceRule | ソースパスワードと一致した場合許容しない(HistoryRuleと似たような使い方?ちょっと良くわかりませんでした) |
DigestSourceRule | ソースパスワードとハッシュ化して比較した上で許容しない |
RepeatCharacterRegexRule | 同じ文字が連続した場合許容しない |
RepeatCharactersRule | 同じ文字の繰り返しを指定回数以上行った場合許容しない |
UsernameRule | ユーザ名を含んだ場合許容しない |
WhitespaceRule | 空白(改行やタブも含む)を許容しない |
まとめ:Javaでパスワードの生成・検証を行うならPassayを使おう
パスワードの生成・検証を行う場合、Passayを使うと便利です。
もちろん正規表現などを用いて同じことをできるのですが、自分で作るよりすでに実績のあるライブラリを使うほうがバグも少なくなります。
あまりメジャーなライブラリではないので情報が少ないのは残念ですが、基本的な使い方はこの記事だけでもできるはずです。
利用する機会があったら参考にしてください。
コメント