パスワード検証用のRegexp Java


109

Javaアプリケーションで構成パラメーターとして使用されるパスワード検証の正規表現を作成しています。

正規表現は次のとおりです。

^.*(?=.{8,})(?=..*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$

パスワードポリシーは次のとおりです。

  • 8文字以上

  • 少なくとも1つの数字が含まれています

  • 少なくとも1つの下位アルファ文字と1つの上位アルファ文字が含まれています

  • 特殊文字のセット(@#%$^など)内に少なくとも1つの文字が含まれています

  • スペース、タブなどを含まない

ポイント5だけがありません。スペース、タブ、キャリッジリターンなどの正規表現チェックを行うことができません。

誰か助けてもらえますか?


3
パスワードルールが不適切です。詳細については、リファレンス-パスワード検証参照してください。
ctwheels

回答:


317

これを試して:

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\S+$).{8,}$

説明:

^                 # start-of-string
(?=.*[0-9])       # a digit must occur at least once
(?=.*[a-z])       # a lower case letter must occur at least once
(?=.*[A-Z])       # an upper case letter must occur at least once
(?=.*[@#$%^&+=])  # a special character must occur at least once
(?=\S+$)          # no whitespace allowed in the entire string
.{8,}             # anything, at least eight places though
$                 # end-of-string

すべてのルールは独立した「モジュール」であるため、個々のルールを簡単に追加、変更、または削除できます。

(?=.*[xyz])コンストラクト食べる文字列全体(.*)と最初の発生までバックトラック[xyz]一致させることができます。[xyz]見つかった場合は成功し、見つからなかった場合は失敗します。

代わりの方法は、消極的な修飾子を使用することです(?=.*?[xyz])。パスワードチェックの場合、これはほとんど違いがありません。非常に長い文字列の場合、より効率的なバリアントになる可能性があります。

もちろん、最も効率的なバリアント(ただし、読み取りと保守が最も難しく、エラーが発生しやすい)は(?=[^xyz]*[xyz])です。この長さの正規表現とこの目的のためには、実際の利点がないので、そのように実行することはお勧めしません。


15
@ Kerby82:Java文字列では、バックスラッシュをエスケープする必要があります。使用してみてください\\s。これはJavaの要件であり、正規表現の要件ではありません。
Tomalak

1
@Allovちょうどそのように考えてください。強制されないものはすべてオプションです。強制したくないもののチェックを外すだけです。ソリューションをニーズに合わせて簡単に調整できる必要があります。
Tomalak

3
この回答は、「一般的な検証タスク」のスタックオーバーフローの正規表現に関するFAQに追加されました。
aliteralmind 2014

1
@ shA.t同じです。私は唯一の維持しようとした(?=...)、それは式の残りの部分の設定と一致するようにパターンを...
Tomalak

2
@ shA.t「スペース以外の文字のみが含まれている」((?=\S+$))か「スペースが含まれていない」()か(?!.*\s)は、好みの問題です。好きなものを使ってください。:)
Tomalak 2015

55

正規表現を使用した簡単な例

public class passwordvalidation {
    public static void main(String[] args) {
      String passwd = "aaZZa44@"; 
      String pattern = "(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}";
      System.out.println(passwd.matches(pattern));
   }
}

説明:

  • (?=.*[0-9]) 数字は少なくとも1回出現する必要があります
  • (?=.*[a-z]) 小文字は少なくとも1回出現する必要があります
  • (?=.*[A-Z]) 大文字は少なくとも1回出現する必要があります
  • (?=.*[@#$%^&+=]) 特殊文字は少なくとも1回出現する必要があります
  • (?=\\S+$) 文字列全体に空白を含めることはできません
  • .{8,} 8文字以上

5
。{5,10}は、最小5文字、最大10文字を表します。誰かが具体的な説明を求めている場合に備えて。
abhy 2015

@iabhi、私はこれを探していました。ありがとうございました。
Akshatha Srinivas、2018

セキュリティ上の理由から、文字列ではなく文字配列に格納されているパスワードに正規表現を実装しようとしています。しかし、どのようにして正規表現をchar配列に適用しますか?
AgentM 2018年

13

以前に与えられたすべての回答は、同じ(正しい)手法を使用して、要件ごとに個別の先読みを使用します。しかし、実際にはパスワードを使用するバックエンドに応じて、いくつかの非効率性と潜在的に大規模なバグが含まれています。

受け入れられた答えの正規表現から始めます:

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\S+$).{8,}$

Javaサポートしているため、すべての最初に、\A\z私は独立の、必ず文字列全体が検証されていることを確認するために、これらを使用することを好みますPattern.MULTILINE。これはパフォーマンスには影響しませんが、正規表現がリサイクルされるときの間違いを回避します。

\A(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\S+$).{8,}\z

パスワードに空白が含まれていないことの確認とその最小長の確認は、許可される文字を制限する{8,}略記に可変数量詞を置くことにより、一度にすべてのパスを使用し\Sて実行できます。

\A(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])\S{8,}\z

提供されたパスワードにスペースが含まれている場合、すべてのチェックが実行され、スペースの最終チェックが失敗するだけです。これは、すべてのドットを\S次のように置き換えることで回避できます。

\A(?=\S*[0-9])(?=\S*[a-z])(?=\S*[A-Z])(?=\S*[@#$%^&+=])\S{8,}\z

ドットは、本当に文字を許可したい場合にのみ使用してください。それ以外の場合は、(否定された)文字クラスを使用して、正規表現を本当に許可されている文字のみに制限します。この場合、それはほとんど違いがありませんが、他のより適切なときにドットを使用しないことは非常に良い習慣です。ドットよりも適切なものを使用するのに開発者が怠惰だったため、壊滅的なバックトラッキングのケースが多すぎます。

最初のテストでパスワードの前半に適切な文字が見つかる可能性が高いため、遅延量指定子の方が効率的です。

\A(?=\S*?[0-9])(?=\S*?[a-z])(?=\S*?[A-Z])(?=\S*?[@#$%^&+=])\S{8,}\z

しかし、ここで本当に重要な問題について説明します。いずれの回答も、元の質問がASCIIで考える誰かによって書かれたように見えるという事実について言及していません。しかし、Javaの文字列はUnicodeです。パスワードに非ASCII文字を使用できますか?そうである場合は、ASCIIスペースのみが許可されていないか、すべてのUnicode空白を除外する必要があります。

デフォルト\sでは、ASCIIの空白のみと一致するため、その逆は\SすべてのUnicode文字(空白かどうか)と空白以外のすべてのASCII文字と一致します。Unicode文字は許可されているがUnicodeスペースは許可されていない場合は、UNICODE_CHARACTER_CLASSフラグを指定して\SUnicode空白を除外できます。Unicode文字が許可されていない場合は、[\x21-\x7E]代わりに使用\Sして、スペースまたは制御文字ではないすべてのASCII文字を照合できます。

これにより、次の潜在的な問題が発生します。制御文字を許可しますか?適切な正規表現を作成する最初のステップは、一致させたいものと一致させないものを正確に指定することです。唯一の100%技術的に正しい答えは、制御文字や非ASCII文字などの特定の範囲の文字が許可されているかどうかが記載されていないため、質問のパスワードの指定があいまいであることです。


9

過度に複雑な正規表現(回避できる場合)は使用しないでください。

  • 読みにくい(少なくとも自分以外のすべての人にとって)
  • 伸びにくい
  • デバッグが難しい

多くの小さな正規表現を使用するとパフォーマンスのオーバーヘッドがわずかに発生する可能性がありますが、上記の点は簡単にそれを上回ります。

私はこのように実装します:

bool matchesPolicy(pwd) {
    if (pwd.length < 8) return false;
    if (not pwd =~ /[0-9]/) return false;
    if (not pwd =~ /[a-z]/) return false;
    if (not pwd =~ /[A-Z]/) return false;
    if (not pwd =~ /[%@$^]/) return false;
    if (pwd =~ /\s/) return false;
    return true;
}

セキュリティの観点からは、パスワードを非常に複雑で覚えにくいものにする代わりに、より長いパスワードを強制し、よく知られているパスワード(12345やpass = userなど)を防止する方がはるかに優れています。
Martin Rauscher

上記のアプローチが好きです。有難うございます!
トーマスラング

1

パスワード要件:

  • パスワードは、システムがサポートできる長さで8文字以上にする必要があります。
  • パスワードには、英数字、特殊文字の2つ以上のグループの文字を含める必要があります。

    ^.*(?=.{8,})(?=.*\d)(?=.*[a-zA-Z])|(?=.{8,})(?=.*\d)(?=.*[!@#$%^&])|(?=.{8,})(?=.*[a-zA-Z])(?=.*[!@#$%^&]).*$

私はそれをテストし、それは動作します


1

各タイプのキャラクターの最小要件に興味がある人は、トマラックの受け入れられた回答を次のように拡張することをお勧めします。

^(?=(.*[0-9]){%d,})(?=(.*[a-z]){%d,})(?=(.*[A-Z]){%d,})(?=(.*[^0-9a-zA-Z]){%d,})(?=\S+$).{%d,}$

これはフォーマット文字列であり、最終的な正規表現パターンではないことに注意してください。%dを、数字、小文字、大文字、非数字/文字、およびパスワード全体(それぞれ)の最低限必要なオカレンスに置き換えてください。最大出現数はほとんどありません(最大0が必要で、そのような文字を効果的に拒否しない限り)が、それらも簡単に追加できます。各タイプの周りの余分なグループ化に注意してください。これにより、最小/最大の制約により、連続しない一致が可能になります。これは、必要な各タイプの文字の数を一元的に構成し、Webサイトと2つの異なるモバイルプラットフォームにその情報をフェッチさせて、上記のフォーマット文字列に基づいて正規表現パターンを構築できるシステムでは不思議に機能しました。


1

これはすべての特殊文字をチェックします:

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=\S+$).*[A-Za-z0-9].{8,}$

1

パラメータ付きのJavaメソッド

コピーして貼り付け、必要なパラメータを設定するだけです。

モジュールが必要ない場合は、コメントするか、私が特別な文字について行った「if」を追加してください

//______________________________________________________________________________
/**
 * Validation Password     */
//______________________________________________________________________________
private static boolean validation_Password(final String PASSWORD_Arg)    {
    boolean result = false;
    try {
        if (PASSWORD_Arg!=null) {
            //_________________________
            //Parameteres
            final String MIN_LENGHT="8";
            final String MAX_LENGHT="20";
            final boolean SPECIAL_CHAR_NEEDED=true;

            //_________________________
            //Modules
            final String ONE_DIGIT = "(?=.*[0-9])";  //(?=.*[0-9]) a digit must occur at least once
            final String LOWER_CASE = "(?=.*[a-z])";  //(?=.*[a-z]) a lower case letter must occur at least once
            final String UPPER_CASE = "(?=.*[A-Z])";  //(?=.*[A-Z]) an upper case letter must occur at least once
            final String NO_SPACE = "(?=\\S+$)";  //(?=\\S+$) no whitespace allowed in the entire string
            //final String MIN_CHAR = ".{" + MIN_LENGHT + ",}";  //.{8,} at least 8 characters
            final String MIN_MAX_CHAR = ".{" + MIN_LENGHT + "," + MAX_LENGHT + "}";  //.{5,10} represents minimum of 5 characters and maximum of 10 characters

            final String SPECIAL_CHAR;
            if (SPECIAL_CHAR_NEEDED==true) SPECIAL_CHAR= "(?=.*[@#$%^&+=])"; //(?=.*[@#$%^&+=]) a special character must occur at least once
            else SPECIAL_CHAR="";
            //_________________________
            //Pattern
            //String pattern = "(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}";
            final String PATTERN = ONE_DIGIT + LOWER_CASE + UPPER_CASE + SPECIAL_CHAR + NO_SPACE + MIN_MAX_CHAR;
            //_________________________
            result = PASSWORD_Arg.matches(PATTERN);
            //_________________________
        }    

    } catch (Exception ex) {
        result=false;
    }

    return result;
}        


0

私はこれも(より簡単なモードとして)それを行うことができると思います:

^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])[^\s]{8,}$

[正規表現のデモ]


0

簡単なもの

( "^(?=。* [0-9])(?=。* [az])(?=。* [AZ])(?=。* [\\ W _])[\\ S] {8 、10} $ ")

  1. (?=何か)->すべての入力文字列で前向きに検索し、この条件が.sample(?=。* [0-9])->と書かれていることを確認することは、すべての文字列に1桁の数字が書かれていることを意味します。書かれていない場合falseを返します

  2. (?!何か)->(逆も同様)は、条件が書き込まれた場合に否定的な前向きを意味し、falseを返します

    近い意味^(条件)(条件)(条件)(条件)[\ S] {8,10} $


コードのみの回答は問題の解決策を提供する可能性がありますが、一部の説明は回答の質を大幅に改善します。
Nigel Ren

0
String s=pwd;
int n=0;
for(int i=0;i<s.length();i++)
{
    if((Character.isDigit(s.charAt(i))))
    {
        n=5;
        break;
    }
    else
    {

    }
}
for(int i=0;i<s.length();i++)
{
    if((Character.isLetter(s.charAt(i))))
    {
        n+=5;
        break;
    }
    else
    {

    }

}

if(n==10)
{
    out.print("Password format correct <b>Accepted</b><br>");

}
else
{
    out.print("Password must be alphanumeric <b>Declined</b><br>");
}

説明:

  1. 最初にパスワードを文字列として設定し、整数セットoを作成します。
  2. 次に、forループですべての文字を確認します。
  3. 文字列で数値が見つかった場合、nは5を加算します。次に、次のforループにジャンプします。 Character.isDigit(s.charAt(i))
  4. このループは、文字列に配置されたアルファベットをチェックします。見つかった場合は、nにさらに5を追加します。Character.isLetter(s.charAt(i))
  5. 次に、if条件によって整数nを確認します。n = 10がtrueの場合、与えられた文字列は英数字で、それ以外の場合はそうではありません。

0

また、あなたはこのようにすることができます。

 public boolean isPasswordValid(String password) {


    String regExpn =
            "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}$";

    CharSequence inputStr = password;

    Pattern pattern = Pattern.compile(regExpn,Pattern.CASE_INSENSITIVE);
    Matcher matcher = pattern.matcher(inputStr);

    if(matcher.matches())
        return true;
    else
        return false;
}

0

強力なパスワードのサンプルコードブ​​ロック:

(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9])(?=\\S+$).{6,18}
  1. 少なくとも6桁
  2. 18桁まで
  3. ワンナンバー
  4. 1つの小文字
  5. 1つの大文字
  6. すべての特殊文字を含めることができます

0

RegExは-

^(?:(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*)[^\s]{8,}$
  1. 少なくとも8桁{8、}
  2. 少なくとも1つの数値(?=。* \ d)
  3. 少なくとも1つの小文字(?=。* [az])
  4. 少なくとも1つの大文字(?=。* [AZ])
  5. 少なくとも1つの特殊文字(?=。* [@#$%^&+ =])
  6. スペースなし[^ \ s]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.