Regexp Java untuk validasi kata sandi

109

Saya membuat regexp untuk validasi sandi yang akan digunakan dalam aplikasi Java sebagai parameter konfigurasi.

Regexpnya adalah:

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

Kebijakan kata sandi adalah:

  • Setidaknya 8 karakter

  • Berisi setidaknya satu digit

  • Berisi setidaknya satu karakter alfa bawah dan satu karakter alfa atas

  • Berisi setidaknya satu karakter dalam satu set karakter khusus ( @#%$^dll.)

  • Tidak mengandung spasi, tab, dll.

Saya melewatkan poin 5. Saya tidak dapat memiliki pemeriksaan regexp untuk spasi, tab, carriage return, dll.

Adakah yang bisa membantu saya?

Kerby82
sumber
3
Aturan kata sandi buruk. Silakan lihat Referensi - Validasi Kata Sandi untuk info lebih lanjut.
ctwheels

Jawaban:

317

Coba ini:

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

Penjelasan:

^                 # 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

Sangat mudah untuk menambah, mengubah atau menghapus aturan individu, karena setiap aturan adalah "modul" independen.

The (?=.*[xyz])konstruk makan seluruh string ( .*) dan backtracks untuk kejadian pertama di mana [xyz]bisa cocok. Berhasil jika [xyz]ditemukan, gagal jika tidak.

Alternatif akan menggunakan kualifikasi enggan: (?=.*?[xyz]). Untuk pemeriksaan kata sandi, ini tidak akan membuat perbedaan apa pun, untuk string yang lebih panjang, ini bisa menjadi varian yang lebih efisien.

Varian yang paling efisien (tetapi yang paling sulit dibaca dan dipelihara, oleh karena itu yang paling rawan kesalahan) (?=[^xyz]*[xyz]), tentu saja. Untuk regex dengan panjang ini dan untuk tujuan ini, saya tidak akan merekomendasikan melakukannya dengan cara itu, karena tidak memiliki manfaat nyata.

Tomalak
sumber
15
@ Kerby82: Dalam string Java, garis miring terbalik harus dihilangkan. Coba gunakan \\s. Itu adalah persyaratan Java, bukan persyaratan regex.
Tomalak
1
@Allov Coba pikirkan seperti itu: Segala sesuatu yang tidak diberlakukan adalah opsional. Hapus saja pemeriksaan untuk hal-hal yang tidak ingin Anda terapkan. Harus mudah menyesuaikan solusi dengan kebutuhan Anda.
Tomalak
3
Jawaban ini telah ditambahkan ke FAQ Ekspresi Reguler Stack Overflow , di bawah "Tugas Validasi Umum".
aliteralmind
1
@ shA.t Itu hal yang sama. Saya hanya mencoba untuk mempertahankan (?=...)polanya sehingga cocok dengan pengaturan ekspresi lainnya ..
Tomalak
2
@ shA.t Apakah Anda mengatakan "hanya berisi karakter bukan spasi" ( (?=\S+$)) atau "tidak berisi karakter spasi" ( (?!.*\s)) adalah masalah preferensi. Gunakan apa pun yang Anda suka dengan lebih baik. :)
Tomalak
55

contoh sederhana menggunakan regex

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

Penjelasan:

  • (?=.*[0-9]) satu digit harus muncul setidaknya sekali
  • (?=.*[a-z]) huruf kecil harus muncul setidaknya sekali
  • (?=.*[A-Z]) huruf besar harus muncul setidaknya sekali
  • (?=.*[@#$%^&+=]) karakter khusus harus muncul setidaknya sekali
  • (?=\\S+$) tidak ada spasi kosong yang diperbolehkan di seluruh string
  • .{8,} setidaknya 8 karakter
tangkas
sumber
5
. {5,10} mewakili minimal 5 karakter dan maksimal 10 karakter. Untuk berjaga-jaga jika ada yang mencari penjelasan spesifik.
abhy
@iabhi, saya mencari ini. Terima kasih.
Akshatha Srinivas
Saya mencoba menerapkan Regex pada sandi yang disimpan dalam array karakter, bukan String karena keamanan. Tapi bagaimana cara menerapkan regex ke array karakter?
AgentM
13

Semua jawaban yang diberikan sebelumnya menggunakan teknik yang sama (benar) untuk menggunakan lookahead terpisah untuk setiap persyaratan. Tetapi mereka mengandung beberapa inefisiensi dan bug yang berpotensi besar, tergantung pada bagian belakang yang benar-benar akan menggunakan kata sandi.

Saya akan mulai dengan regex dari jawaban yang diterima:

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

Pertama-tama, karena Java mendukung \Adan \zsaya lebih suka menggunakannya untuk memastikan seluruh string divalidasi, terlepas dari Pattern.MULTILINE. Ini tidak memengaruhi kinerja, tetapi menghindari kesalahan saat ekspresi reguler didaur ulang.

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

Memeriksa bahwa kata sandi tidak mengandung spasi dan memeriksa panjang minimumnya dapat dilakukan dalam sekali jalan dengan menggunakan semua sekaligus dengan meletakkan pembilang variabel {8,}pada singkatan \Syang membatasi karakter yang diizinkan:

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

Jika kata sandi yang diberikan memang mengandung spasi, semua pemeriksaan akan dilakukan, hanya untuk pemeriksaan terakhir gagal pada spasi. Ini dapat dihindari dengan mengganti semua titik dengan \S:

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

Titik hanya boleh digunakan jika Anda benar-benar ingin mengizinkan karakter apa pun. Jika tidak, gunakan kelas karakter (dinegasikan) untuk membatasi regex Anda hanya untuk karakter yang benar-benar diizinkan. Meskipun dalam kasus ini tidak ada bedanya, tidak menggunakan titik saat ada hal lain yang lebih sesuai adalah kebiasaan yang sangat baik. Saya melihat terlalu banyak kasus catastrophic backtracking karena pengembang terlalu malas untuk menggunakan sesuatu yang lebih sesuai daripada titik.

Karena ada kemungkinan besar pengujian awal akan menemukan karakter yang sesuai di paruh pertama kata sandi, penghitung malas bisa lebih efisien:

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

Tetapi sekarang untuk masalah yang sangat penting: tidak ada jawaban yang menyebutkan fakta bahwa pertanyaan asli tampaknya ditulis oleh seseorang yang berpikir dalam ASCII. Tetapi dalam string Java adalah Unicode. Apakah karakter non-ASCII diperbolehkan dalam sandi? Jika ya, hanya spasi ASCII yang tidak diizinkan, atau semua spasi Unicode harus dikecualikan.

Secara default \shanya mencocokkan ruang putih ASCII, jadi kebalikannya \Scocok dengan semua karakter Unicode (spasi atau tidak) dan semua karakter ASCII non-spasi. Jika karakter Unicode diizinkan tetapi spasi Unicode tidak diperbolehkan, UNICODE_CHARACTER_CLASSbendera dapat ditentukan untuk \Smengecualikan spasi kosong Unicode. Jika karakter Unicode tidak diperbolehkan, maka [\x21-\x7E]dapat digunakan sebagai pengganti \Suntuk mencocokkan semua karakter ASCII yang bukan spasi atau karakter kontrol.

Yang membawa kita ke masalah potensial berikutnya: apakah kita ingin mengizinkan karakter kontrol? Langkah pertama dalam menulis regex yang tepat adalah menentukan dengan tepat apa yang ingin Anda cocokkan dan apa yang tidak. Satu-satunya jawaban yang 100% benar secara teknis adalah bahwa spesifikasi kata sandi dalam pertanyaan itu ambigu karena tidak menyatakan apakah rentang karakter tertentu seperti karakter kontrol atau karakter non-ASCII diizinkan atau tidak.

Jan Goyvaerts
sumber
9

Anda tidak boleh menggunakan Regex yang terlalu kompleks (jika Anda dapat menghindarinya) karena memang demikian

  • sulit dibaca (setidaknya untuk semua orang kecuali diri Anda sendiri)
  • sulit untuk diperpanjang
  • sulit untuk di-debug

Meskipun mungkin ada overhead kinerja kecil dalam menggunakan banyak ekspresi reguler kecil, poin di atas membuatnya lebih mudah.

Saya akan menerapkan seperti ini:

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;
}
Martin Rauscher
sumber
Dan dari perspektif keamanan, jauh lebih baik memaksakan kata sandi yang lebih panjang, mencegah kata sandi terkenal (seperti 12345 dan pass = pengguna) daripada membuat kata sandi menjadi sangat rumit dan sulit diingat.
Martin Rauscher
Saya suka pendekatan Anda di atas. Terima kasih untuk itu!
Thomas Lang
1

Persyaratan Kata Sandi:

  • Kata sandi harus setidaknya delapan (8) karakter di mana sistem dapat mendukungnya.
  • Kata sandi harus menyertakan karakter dari setidaknya dua (2) pengelompokan ini: alfa, numerik, dan karakter khusus.

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

Saya mengujinya dan berhasil

Andrew
sumber
1

Bagi siapa pun yang tertarik dengan persyaratan minimum untuk setiap jenis karakter, saya sarankan untuk membuat ekstensi berikut atas jawaban yang diterima Tomalak:

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

Perhatikan bahwa ini adalah string pemformatan dan bukan pola regex terakhir. Cukup gantikan% d dengan kemunculan minimum yang diperlukan untuk: digit, huruf kecil, huruf besar, bukan digit / karakter, dan seluruh kata sandi (masing-masing). Kemunculan maksimum tidak mungkin (kecuali Anda menginginkan maksimal 0, secara efektif menolak karakter seperti itu) tetapi itu dapat dengan mudah ditambahkan juga. Perhatikan pengelompokan ekstra di sekitar setiap jenis sehingga batasan min / max memungkinkan kecocokan yang tidak berurutan. Ini bekerja dengan sangat baik untuk sistem di mana kita dapat secara terpusat mengkonfigurasi berapa banyak dari setiap jenis karakter yang kita butuhkan dan kemudian memiliki situs web serta dua platform seluler yang berbeda mengambil informasi itu untuk membangun pola regex berdasarkan string pemformatan di atas.

Demetrios Christopher
sumber
1

Yang ini memeriksa setiap karakter khusus:

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

Metode Java siap untuk Anda, dengan parameter

Cukup salin dan tempel dan atur parameter yang Anda inginkan.

Jika Anda tidak menginginkan modul, cukup beri komentar atau tambahkan "jika" seperti yang saya lakukan untuk karakter khusus

//______________________________________________________________________________
/**
 * 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;
}        
Fausto70
sumber
1

Gunakan perpustakaan Passay yang merupakan api yang kuat.

Balasubramanian Rengasamy
sumber
0

Saya pikir ini juga dapat dilakukan (sebagai mode yang lebih sederhana):

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

[Demo Regex]

shA.t
sumber
0

mudah

("^ (? =. * [0-9]) (? =. * [Az]) (? =. * [AZ]) (? =. * [\\ W _]) [\\ S] {8 , 10} $ ")

  1. (? = apa saja) -> berarti positif melihat ke depan pada semua string input dan pastikan untuk kondisi ini tertulis .sample (? =. * [0-9]) -> berarti memastikan satu digit angka tertulis di semua string. jika tidak tertulis return false .

  2. (?! apa saja) -> (sebaliknya) berarti negatif melihat ke depan jika kondisinya tertulis return false .

    arti dekat ^ (kondisi) (kondisi) (kondisi) (kondisi) [\ S] {8,10} $

ibrahem shabban
sumber
Meskipun jawaban hanya kode dapat memberikan solusi untuk masalah tersebut, beberapa penjelasan akan sangat meningkatkan kualitas jawaban.
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>");
}

Penjelasan:

  1. Pertama atur kata sandi sebagai string dan buat bilangan bulat set o.
  2. Kemudian periksa setiap karakter oleh for loop.
  3. Jika menemukan angka dalam string maka n tambahkan 5. Kemudian lompat ke loop for berikutnya. Character.isDigit (s.charAt (i))
  4. Perulangan ini memeriksa huruf apa pun yang ditempatkan dalam string. Jika menemukan maka tambahkan satu lagi 5 di n. Character.isLetter (s.charAt (i))
  5. Sekarang periksa bilangan bulat n dengan cara if condition. Jika n = 10 benar, string yang diberikan adalah alfanumerik jika tidak maka tidak.
Naresh Babu
sumber
0

Anda Juga Dapat Melakukan Seperti Ini.

 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;
}
RANAJEET BARIK
sumber
0

Contoh blok kode untuk kata sandi yang kuat:

(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9])(?=\\S+$).{6,18}
  1. setidaknya 6 digit
  2. hingga 18 digit
  3. satu nomor
  4. satu huruf kecil
  5. satu huruf besar
  6. dapat berisi semua karakter khusus
Sedrettin Çalışkan
sumber
0

RegEx adalah -

^(?:(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*)[^\s]{8,}$
  1. setidaknya 8 digit {8,}
  2. setidaknya satu angka (? =. * \ d)
  3. setidaknya satu huruf kecil (? =. * [az])
  4. setidaknya satu huruf besar (? =. * [AZ])
  5. setidaknya satu karakter khusus (? =. * [@ # $% ^ & + =])
  6. Tidak ada spasi [^ \ s]
Ankit Kumar Rajpoot
sumber