Regexp Java để xác thực mật khẩu


109

Tôi đang tạo một regexp để xác thực mật khẩu được sử dụng trong ứng dụng Java làm tham số cấu hình.

Regexp là:

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

Chính sách mật khẩu là:

  • Ít nhất 8 ký tự

  • Chứa ít nhất một chữ số

  • Chứa ít nhất một ký tự alpha dưới và một ký tự alpha trên

  • Chứa ít nhất một ký tự trong một tập hợp các ký tự đặc biệt ( @#%$^v.v.)

  • Không chứa khoảng trắng, tab, v.v.

Tôi chỉ thiếu điểm 5. Tôi không thể kiểm tra regexp cho khoảng trắng, tab, dấu xuống dòng, v.v.

Có ai giúp tôi không?


3
Quy tắc mật khẩu là xấu. Vui lòng xem Tham khảo - Xác thực mật khẩu để biết thêm thông tin.
ctwheels

Câu trả lời:


317

Thử cái này:

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

Giải trình:

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

Thật dễ dàng để thêm, sửa đổi hoặc xóa các quy tắc riêng lẻ, vì mọi quy tắc là một "mô-đun" độc lập.

Cấu (?=.*[xyz])trúc ăn toàn bộ chuỗi ( .*) và dấu lùi đến lần xuất hiện đầu tiên ở những nơi [xyz]có thể khớp. Nó thành công nếu [xyz]được tìm thấy, nó sẽ thất bại nếu không.

Việc thay thế sẽ được sử dụng một vòng bất đắc dĩ: (?=.*?[xyz]). Đối với kiểm tra mật khẩu, điều này sẽ hầu như không tạo ra bất kỳ sự khác biệt nào, đối với các chuỗi dài hơn, nó có thể là biến thể hiệu quả hơn.

Tất nhiên, biến thể hiệu quả nhất (nhưng khó đọc và khó bảo trì nhất, do đó dễ xảy ra lỗi nhất) (?=[^xyz]*[xyz]). Đối với một regex có độ dài như vậy và cho mục đích này, tôi không khuyên bạn nên làm theo cách đó, vì nó không có lợi ích thực sự.


15
@ Kerby82: Trong chuỗi Java, dấu gạch chéo ngược phải được thoát ra. Cố gắng sử dụng \\s. Đó là một yêu cầu Java, không phải là một yêu cầu regex.
Tomalak

1
@Allov Chỉ cần nghĩ về nó theo cách đó: Mọi thứ không được thực thi là tùy chọn. Chỉ cần xóa kiểm tra những thứ bạn không muốn thực thi. Nên dễ dàng điều chỉnh giải pháp theo nhu cầu của bạn.
Tomalak

3
Câu trả lời này đã được thêm vào Câu hỏi Thường Gặp về Cụm từ Thông dụng Stack Overflow , trong "Nhiệm vụ Xác thực Thông thường".
aliteralmind

1
@ shA.t Cũng vậy thôi. Tôi chỉ cố gắng để giữ cho các (?=...)mô hình để nó phù hợp với thiết lập của phần còn lại của biểu thức ..
Tomalak

2
@ shA.t Cho dù bạn nói "chỉ chứa các ký tự không phải khoảng trắng" ( (?=\S+$)) hay "không chứa các ký tự khoảng trắng " ( (?!.*\s)) là một vấn đề tùy chọn. Sử dụng bất cứ điều gì bạn thích tốt hơn. :)
Tomalak

55

ví dụ đơn giản bằng cách sử dụng 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));
   }
}

Giải thích:

  • (?=.*[0-9]) một chữ số phải xuất hiện ít nhất một lần
  • (?=.*[a-z]) một chữ cái thường phải xuất hiện ít nhất một lần
  • (?=.*[A-Z]) một chữ cái viết hoa phải xuất hiện ít nhất một lần
  • (?=.*[@#$%^&+=]) một ký tự đặc biệt phải xuất hiện ít nhất một lần
  • (?=\\S+$) không cho phép khoảng trắng trong toàn bộ chuỗi
  • .{8,} ít nhất 8 ký tự

5
. {5,10} đại diện cho tối thiểu 5 ký tự và tối đa 10 ký tự. Chỉ trong trường hợp có ai đó đang tìm kiếm lời giải thích cụ thể.
abhy

@iabhi, tôi đang tìm kiếm cái này. Cảm ơn bạn.
Akshatha Srinivas

Tôi đang cố gắng triển khai Regex trên mật khẩu được lưu trữ trong mảng char thay vì Chuỗi vì tính bảo mật. Nhưng làm cách nào để áp dụng regex vào mảng char?
AgentM

13

Tất cả các câu trả lời đã cho trước đó sử dụng cùng một kỹ thuật (đúng) để sử dụng một cái nhìn riêng cho từng yêu cầu. Nhưng chúng chứa một vài điểm kém hiệu quả và một lỗi lớn tiềm ẩn, tùy thuộc vào back end sẽ thực sự sử dụng mật khẩu.

Tôi sẽ bắt đầu với regex từ câu trả lời được chấp nhận:

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

Trước hết, vì Java hỗ trợ \A\ztôi thích sử dụng những thứ đó để đảm bảo toàn bộ chuỗi được xác thực, độc lập với Pattern.MULTILINE. Điều này không ảnh hưởng đến hiệu suất, nhưng tránh sai lầm khi regexes được tái chế.

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

Kiểm tra mật khẩu không chứa khoảng trắng và kiểm tra độ dài tối thiểu của nó có thể được thực hiện trong một lần chuyển bằng cách sử dụng tất cả cùng một lúc bằng cách đặt định lượng biến đổi {8,}trên tốc ký \Sgiới hạn các ký tự được phép:

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

Nếu mật khẩu được cung cấp có chứa dấu cách, tất cả các lần kiểm tra sẽ được thực hiện, chỉ để lần kiểm tra cuối cùng không thành công trên khoảng trống. Điều này có thể tránh được bằng cách thay thế tất cả các dấu chấm bằng \S:

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

Dấu chấm chỉ nên được sử dụng nếu bạn thực sự muốn cho phép bất kỳ ký tự nào. Nếu không, hãy sử dụng một lớp ký tự (bị phủ định) để giới hạn regex của bạn chỉ với những ký tự thực sự được phép. Mặc dù nó có chút khác biệt trong trường hợp này, nhưng không sử dụng dấu chấm khi thứ khác thích hợp hơn là một thói quen rất tốt. Tôi thấy có quá nhiều trường hợp quay trở lại thảm khốc vì nhà phát triển quá lười biếng để sử dụng thứ gì đó phù hợp hơn dấu chấm.

Vì có nhiều khả năng các thử nghiệm ban đầu sẽ tìm thấy một ký tự thích hợp trong nửa đầu của mật khẩu, một bộ định lượng lười biếng có thể hiệu quả hơn:

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

Nhưng bây giờ đối với vấn đề thực sự quan trọng: không có câu trả lời nào đề cập đến thực tế rằng câu hỏi ban đầu dường như được viết bởi ai đó nghĩ trong ASCII. Nhưng trong Java chuỗi là Unicode. Các ký tự không phải ASCII có được phép trong mật khẩu không? Nếu có, thì chỉ những khoảng trắng ASCII không được phép hoặc nên loại trừ tất cả khoảng trắng Unicode.

Theo mặc định, \schỉ khớp với khoảng trắng ASCII, vì vậy nghịch đảo của nó \Skhớp với tất cả các ký tự Unicode (khoảng trắng hoặc không) và tất cả các ký tự ASCII không phải khoảng trắng. Nếu các ký tự Unicode được cho phép nhưng không có dấu cách Unicode, thì UNICODE_CHARACTER_CLASScờ có thể được chỉ định để \Sloại trừ khoảng trắng Unicode. Nếu các ký tự Unicode không được phép, thì [\x21-\x7E]có thể được sử dụng thay thế \Sđể khớp với tất cả các ký tự ASCII không phải là khoảng trắng hoặc ký tự điều khiển.

Điều này đưa chúng ta đến vấn đề tiềm năng tiếp theo: chúng ta có muốn cho phép các ký tự điều khiển không? Bước đầu tiên để viết một regex thích hợp là xác định chính xác những gì bạn muốn khớp và những gì bạn không. Câu trả lời duy nhất đúng 100% về mặt kỹ thuật là thông số kỹ thuật mật khẩu trong câu hỏi không rõ ràng vì nó không nêu rõ liệu một số ký tự nhất định như ký tự điều khiển hoặc ký tự không phải ASCII có được phép hay không.


9

Bạn không nên sử dụng Regex quá phức tạp (nếu bạn có thể tránh chúng) vì chúng

  • khó đọc (ít nhất là đối với tất cả mọi người trừ bản thân bạn)
  • khó mở rộng
  • khó gỡ lỗi

Mặc dù có thể có một chi phí hiệu suất nhỏ khi sử dụng nhiều cụm từ thông dụng nhỏ, nhưng các điểm trên có thể vượt trội hơn một cách dễ dàng.

Tôi sẽ thực hiện như thế này:

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

Và từ góc độ bảo mật, tốt hơn hết là ép các mật khẩu dài hơn, ngăn chặn các mật khẩu nổi tiếng (như 12345 và pass = user) thay vì làm cho mật khẩu siêu phức tạp và khó nhớ.
Martin Rauscher

Tôi thích cách tiếp cận của bạn ở trên. Cảm ơn vì điều đó!
Thomas Lang

1

Yêu cầu mật khẩu:

  • Mật khẩu phải có độ dài ít nhất tám (8) ký tự mà hệ thống có thể hỗ trợ.
  • Mật khẩu phải bao gồm các ký tự từ ít nhất hai (2) trong số các nhóm này: ký tự chữ cái, số và ký tự đặc biệt.

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

Tôi đã thử nghiệm nó và nó hoạt động


1

Đối với bất kỳ ai quan tâm đến yêu cầu tối thiểu cho từng loại nhân vật, tôi khuyên bạn nên tạo phần mở rộng sau cho câu trả lời được chấp nhận của Tomalak:

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

Lưu ý rằng đây là một chuỗi định dạng và không phải là mẫu regex cuối cùng. Chỉ cần thay% d bằng số lần xuất hiện bắt buộc tối thiểu cho: chữ số, chữ thường, chữ hoa, không phải chữ số / ký tự và toàn bộ mật khẩu (tương ứng). Số lần xuất hiện tối đa khó có thể xảy ra (trừ khi bạn muốn số tối đa là 0, từ chối hiệu quả bất kỳ ký tự nào như vậy) nhưng những ký tự đó cũng có thể dễ dàng được thêm vào. Lưu ý nhóm bổ sung xung quanh mỗi loại để các ràng buộc tối thiểu / tối đa cho phép các kết quả phù hợp không liên tiếp. Điều này đã làm nên điều kỳ diệu đối với một hệ thống nơi chúng tôi có thể định cấu hình tập trung số lượng từng loại ký tự mà chúng tôi yêu cầu và sau đó để trang web cũng như hai nền tảng di động khác nhau tìm nạp thông tin đó để xây dựng mẫu regex dựa trên chuỗi định dạng trên.


1

Điều này kiểm tra mọi ký tự đặc biệt:

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

1

Phương pháp Java đã sẵn sàng cho bạn, với các tham số

Chỉ cần sao chép và dán và thiết lập các thông số mong muốn của bạn.

Nếu bạn không muốn mô-đun, chỉ cần nhận xét nó hoặc thêm "nếu" như tôi đã làm cho ký tự đặc biệt

//______________________________________________________________________________
/**
 * 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

Tôi nghĩ điều này cũng có thể làm được (như một chế độ đơn giản hơn):

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

[Regex Demo]


0

dễ dàng

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

  1. (? = anything) -> có nghĩa là tích cực mong đợi trong tất cả chuỗi đầu vào và đảm bảo điều kiện này được viết .sample (? =. * [0-9]) -> có nghĩa là đảm bảo một số có một chữ số được viết trong tất cả chuỗi. nếu không bằng văn bản trả về false .

  2. (?! bất cứ điều gì) -> (ngược lại) có nghĩa là tiêu cực trông chờ nếu điều kiện được viết trả về sai .

    đóng nghĩa ^ (điều kiện) (điều kiện) (điều kiện) (điều kiện) [\ S] {8,10} $


Trong khi câu trả lời chỉ có mã có thể cung cấp giải pháp cho vấn đề, một số giải thích sẽ cải thiện đáng kể chất lượng của câu trả lời.
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>");
}

Giải trình:

  1. Đầu tiên đặt mật khẩu dưới dạng chuỗi và tạo bộ số nguyên o.
  2. Sau đó, kiểm tra từng char của vòng lặp for.
  3. Nếu nó tìm thấy số trong chuỗi thì n thêm 5. Sau đó nhảy sang vòng lặp for tiếp theo. Character.isDigit (s.charAt (i))
  4. Vòng lặp này kiểm tra bất kỳ bảng chữ cái nào được đặt trong chuỗi. Nếu tìm thấy nó thì hãy thêm một số 5 nữa vào n. Character.isLetter (s.charAt (i))
  5. Bây giờ hãy kiểm tra số nguyên n theo điều kiện if. Nếu n = 10 là đúng thì chuỗi cho trước là chữ và số khác thì không.

0

Ngoài ra bạn có thể làm như thế này.

 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

Khối mã mẫu cho mật khẩu mạnh:

(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9])(?=\\S+$).{6,18}
  1. ít nhất 6 chữ số
  2. lên đến 18 chữ số
  3. một số
  4. một chữ thường
  5. một chữ hoa
  6. có thể chứa tất cả các ký tự đặc biệt

0

RegEx là -

^(?:(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*)[^\s]{8,}$
  1. ít nhất 8 chữ số {8,}
  2. ít nhất một số (? =. * \ d)
  3. ít nhất một chữ thường (? =. * [az])
  4. ít nhất một chữ hoa (? =. * [AZ])
  5. ít nhất một ký tự đặc biệt (? =. * [@ # $% ^ & + =])
  6. Không có dấu cách [^ \ s]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.