Regexp Java สำหรับการตรวจสอบรหัสผ่าน


109

ฉันกำลังสร้าง regexp สำหรับการตรวจสอบรหัสผ่านเพื่อใช้ในแอ็พพลิเคชัน Java เป็นพารามิเตอร์คอนฟิกูเรชัน

regexp คือ:

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

นโยบายรหัสผ่านคือ:

  • อย่างน้อย 8 ตัวอักษร

  • ประกอบด้วยตัวเลขอย่างน้อยหนึ่งหลัก

  • มีอักขระอัลฟาที่ต่ำกว่าอย่างน้อยหนึ่งตัวและอักขระอัลฟ่าบน

  • มีอักขระอย่างน้อยหนึ่งตัวในชุดอักขระพิเศษ ( @#%$^ฯลฯ )

  • ไม่มีช่องว่างแท็บ ฯลฯ

ฉันขาดแค่จุดที่ 5 ฉันไม่สามารถตรวจสอบ regexp สำหรับช่องว่างแท็บการคืนรถ ฯลฯ ได้

มีใครช่วยฉันได้บ้าง


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])สร้างกินสตริงทั้งหมด ( .*) และ backtracks ที่จะเกิดขึ้นครั้งแรกที่[xyz]สามารถจับคู่ จะประสบความสำเร็จหาก[xyz]พบก็ล้มเหลวเป็นอย่างอื่น

(?=.*?[xyz])ทางเลือกที่จะใช้คัดเลือกลังเลที่: สำหรับการตรวจสอบรหัสผ่านสิ่งนี้แทบจะไม่สร้างความแตกต่างใด ๆ สำหรับสตริงที่ยาวกว่ามากอาจเป็นตัวแปรที่มีประสิทธิภาพมากกว่า

ตัวแปรที่มีประสิทธิภาพมากที่สุด (แต่อ่านและดูแลรักษายากที่สุดดังนั้นจึงมีโอกาสเกิดข้อผิดพลาดมากที่สุด) (?=[^xyz]*[xyz])แน่นอน สำหรับนิพจน์ทั่วไปที่มีความยาวเท่านี้และเพื่อจุดประสงค์นี้ฉันไม่แนะนำให้ทำเช่นนั้นเนื่องจากไม่มีประโยชน์ที่แท้จริง


15
@ Kerby82: ในสตริง Java ต้องใช้แบ็กสแลช ลองนำไปใช้\\s. นั่นเป็นข้อกำหนดของ Java ไม่ใช่ข้อกำหนด regex
Tomalak

1
@Allov แค่คิดอย่างนั้น: ทุกสิ่งที่ไม่ได้บังคับเป็นทางเลือก เพียงแค่นำการตรวจสอบสิ่งที่คุณไม่ต้องการบังคับใช้ออก ควรปรับแก้ปัญหาให้เข้ากับความต้องการของคุณได้ง่าย
Tomalak

3
คำตอบนี้ได้ถูกเพิ่มเข้าไปในคำถามที่พบบ่อยเกี่ยวกับนิพจน์ทั่วไปของStack Overflowภายใต้ "Common Validation Tasks"
aliteralmind

1
@ shA.t มันเหมือนกัน ฉันแค่พยายามรักษา(?=...)รูปแบบให้ตรงกับการตั้งค่าของส่วนที่เหลือของนิพจน์ ..
Tomalak

2
@ shA.t ไม่ว่าคุณจะพูดว่า "มีเฉพาะอักขระที่ไม่เว้นวรรค" ( (?=\S+$)) หรือ "ไม่มีอักขระเว้นวรรค" ( (?!.*\s)) เป็นเรื่องของการตั้งค่า ใช้อะไรก็ได้ที่คุณชอบดีกว่า :)
Tomalak

55

ตัวอย่างง่ายๆโดยใช้ 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));
   }
}

คำอธิบาย:

  • (?=.*[0-9]) ตัวเลขต้องเกิดขึ้นอย่างน้อยหนึ่งครั้ง
  • (?=.*[a-z]) อักษรตัวพิมพ์เล็กจะต้องเกิดขึ้นอย่างน้อยหนึ่งครั้ง
  • (?=.*[A-Z]) อักษรตัวพิมพ์ใหญ่จะต้องเกิดขึ้นอย่างน้อยหนึ่งครั้ง
  • (?=.*[@#$%^&+=]) อักขระพิเศษต้องเกิดขึ้นอย่างน้อยหนึ่งครั้ง
  • (?=\\S+$) ไม่อนุญาตให้ใช้ช่องว่างในสตริงทั้งหมด
  • .{8,} อย่างน้อย 8 อักขระ

5
. {5,10} หมายถึงอักขระขั้นต่ำ 5 ตัวและสูงสุด 10 อักขระ ในกรณีที่ใครก็ตามกำลังมองหาคำอธิบายที่เฉพาะเจาะจง
abhy

@iabhi ฉันกำลังมองหาสิ่งนี้ ขอบคุณ.
Akshatha Srinivas

ฉันกำลังพยายามใช้ Regex กับรหัสผ่านที่เก็บไว้ในอาร์เรย์ถ่านแทน String เนื่องจากความปลอดภัย แต่จะใช้ regex กับอาร์เรย์ char ได้อย่างไร?
AgentM

13

คำตอบที่ให้ไว้ก่อนหน้านี้ทั้งหมดใช้เทคนิคเดียวกัน (ถูกต้อง) เพื่อใช้การค้นหาที่แยกจากกันสำหรับแต่ละข้อกำหนด แต่มีข้อบกพร่องสองสามข้อและข้อบกพร่องที่อาจเกิดขึ้นได้มากขึ้นอยู่กับส่วนหลังที่จะใช้รหัสผ่านจริงๆ

ฉันจะเริ่มต้นด้วย regex จากคำตอบที่ยอมรับ:

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

ก่อนอื่นเนื่องจาก Java รองรับ\Aและ\zฉันชอบใช้สิ่งเหล่านี้เพื่อให้แน่ใจว่าสตริงทั้งหมดได้รับการตรวจสอบความถูกต้องโดยไม่ขึ้นอยู่กับPattern.MULTILINE. สิ่งนี้ไม่มีผลต่อประสิทธิภาพ แต่หลีกเลี่ยงข้อผิดพลาดเมื่อ regexes ถูกรีไซเคิล

\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

ควรใช้จุดเมื่อคุณต้องการอนุญาตอักขระใด ๆ จริงๆ มิฉะนั้นให้ใช้คลาสอักขระ (ลบ) เพื่อ จำกัด regex ของคุณให้เหลือเฉพาะอักขระที่ได้รับอนุญาตจริงๆ แม้ว่าจะสร้างความแตกต่างเพียงเล็กน้อยในกรณีนี้ แต่การไม่ใช้จุดเมื่อสิ่งอื่นเหมาะสมกว่าเป็นนิสัยที่ดีมาก ฉันเห็นหลายกรณีของการย้อนรอยภัยพิบัติเนื่องจากผู้พัฒนาขี้เกียจเกินไปที่จะใช้สิ่งที่เหมาะสมกว่าจุด

เนื่องจากมีโอกาสดีที่การทดสอบครั้งแรกจะพบอักขระที่เหมาะสมในครึ่งแรกของรหัสผ่านตัวระบุค่าขี้เกียจจึงมีประสิทธิภาพมากขึ้น:

\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แฟล็กสามารถระบุได้เพื่อให้\Sเว้นช่องว่าง Unicode หากไม่อนุญาตให้ใช้อักขระ Unicode [\x21-\x7E]คุณสามารถใช้แทน\Sเพื่อจับคู่อักขระ ASCII ทั้งหมดที่ไม่ใช่ช่องว่างหรืออักขระควบคุม

ซึ่งนำเราไปสู่ปัญหาที่อาจเกิดขึ้นต่อไป: เราต้องการอนุญาตให้ใช้อักขระควบคุมหรือไม่? ขั้นตอนแรกในการเขียน regex ที่ถูกต้องคือการระบุสิ่งที่คุณต้องการจับคู่และสิ่งที่คุณไม่ต้องการ คำตอบที่ถูกต้องทางเทคนิค 100% เท่านั้นคือข้อกำหนดรหัสผ่านในคำถามไม่ชัดเจนเนื่องจากไม่ได้ระบุว่าอนุญาตให้ใช้ช่วงของอักขระบางช่วงเช่นอักขระควบคุมหรืออักขระที่ไม่ใช่ ASCII หรือไม่


9

คุณไม่ควรใช้ Regex ที่ซับซ้อนเกินไป (หากคุณสามารถหลีกเลี่ยงได้) เพราะเป็นเช่นนั้น

  • อ่านยาก (อย่างน้อยก็สำหรับทุกคนยกเว้นตัวคุณเอง)
  • ยากที่จะขยาย
  • ยากที่จะแก้ไขข้อบกพร่อง

แม้ว่าอาจมีค่าใช้จ่ายด้านประสิทธิภาพเล็กน้อยในการใช้นิพจน์ทั่วไปขนาดเล็กจำนวนมาก แต่ประเด็นที่กล่าวมาก็มีน้ำหนักเกินได้อย่างง่ายดาย

ฉันจะใช้สิ่งนี้:

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

ฉันชอบแนวทางของคุณข้างต้น ขอบคุณสำหรับสิ่งนั้น!
Thomas Lang

1

ข้อกำหนดรหัสผ่าน:

  • รหัสผ่านควรมีความยาวอย่างน้อยแปด (8) อักขระที่ระบบสามารถรองรับได้
  • รหัสผ่านต้องมีอักขระจากการจัดกลุ่มเหล่านี้อย่างน้อยสอง (2) ตัว ได้แก่ อัลฟาตัวเลขและอักขระพิเศษ

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

ฉันทดสอบแล้วและใช้งานได้


1

สำหรับใครก็ตามที่สนใจข้อกำหนดขั้นต่ำสำหรับตัวละครแต่ละประเภทฉันขอแนะนำให้สร้างส่วนขยายต่อไปนี้เหนือคำตอบที่ยอมรับของ Tomalak:

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

สังเกตว่านี่เป็นสตริงการจัดรูปแบบไม่ใช่รูปแบบ regex สุดท้าย เพียงแค่แทนที่% d ด้วยจำนวนเหตุการณ์ที่จำเป็นขั้นต่ำสำหรับ: หลักตัวพิมพ์เล็กตัวพิมพ์ใหญ่ไม่ใช่ตัวเลข / อักขระและรหัสผ่านทั้งหมด (ตามลำดับ) จำนวนครั้งสูงสุดไม่น่าจะเกิดขึ้นได้ (เว้นแต่คุณต้องการสูงสุด 0 โดยปฏิเสธอักขระดังกล่าวอย่างมีประสิทธิภาพ) แต่สามารถเพิ่มได้อย่างง่ายดายเช่นกัน สังเกตการจัดกลุ่มพิเศษรอบ ๆ แต่ละประเภทเพื่อให้ข้อ จำกัด ขั้นต่ำ / สูงสุดอนุญาตให้มีการแข่งขันที่ไม่ต่อเนื่องกัน สิ่งนี้ใช้งานได้อย่างมหัศจรรย์สำหรับระบบที่เราสามารถกำหนดค่าจำนวนอักขระแต่ละประเภทที่เราต้องการจากส่วนกลางจากนั้นให้เว็บไซต์รวมถึงแพลตฟอร์มมือถือสองแพลตฟอร์มที่ต่างกันดึงข้อมูลนั้นเพื่อสร้างรูปแบบ regex ตามสตริงการจัดรูปแบบด้านบน


1

อันนี้ตรวจสอบอักขระพิเศษทุกตัว:

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

1

Java Method พร้อมสำหรับคุณพร้อมพารามิเตอร์

เพียงแค่คัดลอกและวางและตั้งค่าพารามิเตอร์ที่คุณต้องการ

หากคุณไม่ต้องการโมดูลเพียงแค่แสดงความคิดเห็นหรือเพิ่ม "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,}$

[Regex Demo]


0

ง่ายอย่างหนึ่ง

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

  1. (? = อะไรก็ได้) -> หมายถึงการมองไปข้างหน้าในเชิงบวกในสตริงอินพุตทั้งหมดและตรวจสอบให้แน่ใจว่ามีการเขียนเงื่อนไขนี้ตัวอย่าง (? =. * [0-9]) -> หมายถึงตรวจสอบให้แน่ใจว่ามีการเขียนตัวเลขหนึ่งหลักในสตริงทั้งหมด ถ้าไม่ได้เขียนผลตอบแทน ที่เป็นเท็จ

  2. (?! อะไร) -> (ในทางกลับกัน) หมายถึงลักษณะเชิงลบไปข้างหน้าถ้าเงื่อนไขเป็นลายลักษณ์อักษรผลตอบแทนที่เป็นเท็จ

    ความหมายใกล้เคียง ^ (เงื่อนไข) (เงื่อนไข) (เงื่อนไข) (เงื่อนไข) [\ 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. จากนั้นตรวจสอบแต่ละตัวอักษรสำหรับลูป
  3. หากพบหมายเลขในสตริงแล้ว n จะเพิ่ม 5 จากนั้นข้ามไปที่ถัดไปเพื่อวนซ้ำ Character.isDigit (s.charAt (i))
  4. ลูปนี้ตรวจสอบตัวอักษรใด ๆ ที่อยู่ในสตริง หากพบแล้วให้เพิ่มอีก 5 ใน n Character.isLetter (s.charAt (i))
  5. ตอนนี้ตรวจสอบจำนวนเต็ม n โดยใช้เงื่อนไข if ถ้า n = 10 เป็นจริงสตริงที่กำหนดเป็นตัวเลขและตัวอักษรอื่นก็ไม่ใช่

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. ตัวพิมพ์เล็กหนึ่งตัว
  5. ตัวพิมพ์ใหญ่หนึ่งตัว
  6. สามารถมีอักขระพิเศษทั้งหมด

0

RegEx คือ -

^(?:(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*)[^\s]{8,}$
  1. อย่างน้อย 8 หลัก {8,}
  2. อย่างน้อยหนึ่งหมายเลข (? =. * \ d)
  3. ตัวพิมพ์เล็กอย่างน้อยหนึ่งตัว (? =. * [az])
  4. ตัวพิมพ์ใหญ่อย่างน้อยหนึ่งตัว (? =. * [AZ])
  5. อักขระพิเศษอย่างน้อยหนึ่งตัว (? =. * [@ # $% ^ & + =])
  6. ไม่มีช่องว่าง [^ \ s]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.