Regex เพื่อตรวจสอบความแข็งแรงของรหัสผ่าน


142

เกณฑ์ความแข็งแรงของรหัสผ่านของฉันเป็นดังนี้:

  • ความยาว 8 ตัวอักษร
  • 2 ตัวอักษรในตัวพิมพ์ใหญ่
  • 1 ตัวละครพิเศษ (!@#$&*)
  • 2 ตัวเลข (0-9)
  • 3 ตัวอักษรในตัวพิมพ์เล็ก

ใครช่วยกรุณาให้ regex ฉันเหมือนกัน เงื่อนไขทั้งหมดต้องเป็นไปตามรหัสผ่าน


2
คุณเต็มใจที่จะเชื่อถือมาตรการรักษาความปลอดภัยรหัสผ่านของคุณกับอินเทอร์เน็ตโดยรวมหรือไม่?
Borealid

12
@Borealid: การเผยแพร่นโยบายรหัสผ่านของคุณจะไม่ส่งผลกระทบต่อความปลอดภัยของคุณอย่างมีนัยสำคัญ หากเป็นเช่นนั้นนโยบายของคุณจะไม่ดี ("เท่านั้นpasswordและhello123เป็นรหัสผ่านที่ถูกต้อง!")
Joachim Sauer

3
@ โจอาคิมซาวเออร์: นั่นไม่ใช่สิ่งที่ฉันหมายถึง สิ่งที่ฉันหมายถึงคือโปสเตอร์อาจจะไว้วางใจสิ่งที่เขาได้รับจาก regex ไม่ใช่ความคิดที่ดี
Borealid

3
ที่จริง regex นี้เป็นไปได้ในรหัสบริการฉันจะได้รับการทดสอบสำหรับกรณี diff ไม่สุ่มสี่สุ่มห้าไว้วางใจได้ :)
Ajay Kelkar

9
กฎรหัสผ่านที่ซับซ้อนมักจะไม่นำไปสู่รหัสผ่านที่ปลอดภัยยิ่งขึ้นสิ่งสำคัญคือความยาวขั้นต่ำเท่านั้น ผู้คนไม่สามารถจำรหัสผ่านที่คาดเดาได้จำนวนมากและกฎดังกล่าวอาจรบกวนการทำงานของรหัสผ่านที่ดี ผู้คนสามารถใช้ความคิดสร้างสรรค์อย่างมากในการข้ามกฎดังกล่าวเช่นโดยใช้รหัสผ่านที่อ่อนแอเช่น "รหัสผ่าน -2014" บ่อยครั้งที่คุณต้องใช้รหัสผ่านที่อ่อนแอกว่าแทนที่จะเป็นรหัสผ่านที่ดีกว่า
martinstoeckli

คำตอบ:


428

คุณสามารถทำการตรวจสอบเหล่านี้โดยใช้การตรวจสอบยืนยันล่วงหน้า:

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

ลิงก์แบบรูบ

คำอธิบาย:

^                         Start anchor
(?=.*[A-Z].*[A-Z])        Ensure string has two uppercase letters.
(?=.*[!@#$&*])            Ensure string has one special case letter.
(?=.*[0-9].*[0-9])        Ensure string has two digits.
(?=.*[a-z].*[a-z].*[a-z]) Ensure string has three lowercase letters.
.{8}                      Ensure string is of length 8.
$                         End anchor.

92
สำหรับใครก็ตามที่ต้องการความยาวอย่างน้อยnให้แทนที่.{8}ด้วย.{n,}
NullUserException

14
+1 สำหรับคำอธิบายที่สมบูรณ์ กฎรหัสผ่านของฉันแตกต่างกัน แต่ขึ้นอยู่กับคำตอบของคุณฉันสามารถปรับเปลี่ยน regex ได้
Morvael

14
ขอบคุณสำหรับการอธิบายว่าเกิดอะไรขึ้นใน regex สิ่งนี้ทำหน้าที่เป็นตัวอย่างการเรียนรู้ที่ยอดเยี่ยมสำหรับพวกเราที่ไม่เคยเรียนรู้เกี่ยวกับไวยากรณ์

4
ฉันขอขอบคุณคำอธิบายของ regex หลายครั้งที่ฉันใช้ regex ที่ซับซ้อนที่ฉันพบโดยไม่เข้าใจว่าเกิดอะไรขึ้น
Nicholas Smith

4
รูปแบบที่ยอดเยี่ยมฉันสงสัยว่าทำไมไม่ใช้ quantifiers อย่างน้อย 1 พิเศษ, 1 หมายเลข, ถ่านพิเศษ 1 ตัว, 8 ตัวอักษร: ^ (? =. * ([AZ]) {1,}) (? =. * [! @ # $ & *] {1,}) ( ? =. * [0-9] {1,}) (? =. * [az] {1,}). {8,100} $
RockOnGom

11

คุณสามารถใช้การค้นหาหัวบวกที่มีความยาวเป็นศูนย์เพื่อระบุข้อ จำกัด แต่ละข้อของคุณแยกจากกัน:

(?=.{8,})(?=.*\p{Lu}.*\p{Lu})(?=.*[!@#$&*])(?=.*[0-9])(?=.*\p{Ll}.*\p{Ll})

หากเครื่องมือ regex ของคุณไม่สนับสนุน\pสัญกรณ์และ ASCII บริสุทธิ์เพียงพอแล้วคุณสามารถแทนที่\p{Lu}ด้วย[A-Z]และมี\p{Ll}[a-z]


8

คำตอบที่ระบุไว้ข้างต้นนั้นสมบูรณ์แบบ แต่ฉันแนะนำให้ใช้ Regex ที่เล็กกว่าหลายรายการแทนที่จะเป็นแบบใหญ่
การแยก regex ยาวมีข้อดีบางประการ:

  • ความง่ายในการเขียนและอ่าน
  • ความสะดวกในการแก้ไขข้อบกพร่อง
  • ความง่ายในการเพิ่ม / ลบส่วนหนึ่งของ regex

โดยทั่วไปวิธีการนี้รหัสเก็บบำรุงรักษาได้อย่างง่ายดาย

ต้องบอกว่าฉันใช้รหัสที่ฉันเขียนในSwiftเป็นตัวอย่าง:

struct RegExp {

    /**
     Check password complexity

     - parameter password:         password to test
     - parameter length:           password min length
     - parameter patternsToEscape: patterns that password must not contains
     - parameter caseSensitivty:   specify if password must conforms case sensitivity or not
     - parameter numericDigits:    specify if password must conforms contains numeric digits or not

     - returns: boolean that describes if password is valid or not
     */
    static func checkPasswordComplexity(password password: String, length: Int, patternsToEscape: [String], caseSensitivty: Bool, numericDigits: Bool) -> Bool {
        if (password.length < length) {
            return false
        }
        if caseSensitivty {
            let hasUpperCase = RegExp.matchesForRegexInText("[A-Z]", text: password).count > 0
            if !hasUpperCase {
                return false
            }
            let hasLowerCase = RegExp.matchesForRegexInText("[a-z]", text: password).count > 0
            if !hasLowerCase {
                return false
            }
        }
        if numericDigits {
            let hasNumbers = RegExp.matchesForRegexInText("\\d", text: password).count > 0
            if !hasNumbers {
                return false
            }
        }
        if patternsToEscape.count > 0 {
            let passwordLowerCase = password.lowercaseString
            for pattern in patternsToEscape {
                let hasMatchesWithPattern = RegExp.matchesForRegexInText(pattern, text: passwordLowerCase).count > 0
                if hasMatchesWithPattern {
                    return false
                }
            }
        }
        return true
    }

    static func matchesForRegexInText(regex: String, text: String) -> [String] {
        do {
            let regex = try NSRegularExpression(pattern: regex, options: [])
            let nsString = text as NSString
            let results = regex.matchesInString(text,
                options: [], range: NSMakeRange(0, nsString.length))
            return results.map { nsString.substringWithRange($0.range)}
        } catch let error as NSError {
            print("invalid regex: \(error.localizedDescription)")
            return []
        }
    }
}

นอกจากนี้เมื่อใช้ regex ที่ซับซ้อนเช่นด้านบนมันเป็นเรื่องง่ายมากที่จะเปิดตัวเองไปสู่การย้อนรอยย้อนกลับอย่างรุนแรง ( regular-expressions.info/catastrophic.html ) วิธีนี้จะไม่มีใครสังเกตจนกว่าเซิร์ฟเวอร์ของคุณจะแฮงค์ด้วย CPU 100% เนื่องจากผู้ใช้ใช้รหัสผ่าน "แปลก" ตัวอย่าง: ^ ([a-z0-9] +) {8,} $ (คุณเห็นข้อผิดพลาดหรือไม่?)
aKzenT


1

โซลูชันของ codaddict ทำงานได้ดี แต่อันนี้มีประสิทธิภาพมากกว่า: (ไวยากรณ์ Python)

password = re.compile(r"""(?#!py password Rev:20160831_2100)
    # Validate password: 2 upper, 1 special, 2 digit, 1 lower, 8 chars.
    ^                        # Anchor to start of string.
    (?=(?:[^A-Z]*[A-Z]){2})  # At least two uppercase.
    (?=[^!@#$&*]*[!@#$&*])   # At least one "special".
    (?=(?:[^0-9]*[0-9]){2})  # At least two digit.
    .{8,}                    # Password length is 8 or more.
    $                        # Anchor to end of string.
    """, re.VERBOSE)

คลาสอักขระที่ถูกทำให้เป็นโมฆะจะกินทุกอย่างจนถึงตัวละครที่ต้องการในขั้นตอนเดียว (โซลูชัน dot star ใช้งานได้ดี แต่ไม่ต้องการ backtracking บ้าง) แน่นอนว่ามีสตริงเป้าหมายสั้น ๆ เช่นรหัสผ่านการปรับปรุงประสิทธิภาพนี้จะเล็กน้อย


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

@lospejos - # ไม่ใช่จุดเริ่มต้นของความคิดเห็นหนึ่งบรรทัดปกติ กัญชานี้เป็นส่วนหนึ่งของกลุ่มความคิดเห็นที่เริ่มต้นด้วยและจบลงด้วยการ(?# )ไม่มี parens ที่ไม่สมดุลใน regex นี้
ridgerunner

1
import re

RegexLength=re.compile(r'^\S{8,}$')
RegexDigit=re.compile(r'\d')
RegexLower=re.compile(r'[a-z]')
RegexUpper=re.compile(r'[A-Z]')


def IsStrongPW(password):
    if RegexLength.search(password) == None or RegexDigit.search(password) == None or RegexUpper.search(password) == None or RegexLower.search(password) == None:
        return False
    else:
        return True

while True:
    userpw=input("please input your passord to check: \n")
    if userpw == "exit":
        break
    else:
        print(IsStrongPW(userpw))

1

วิธีการแก้ปัญหาของ @ codaddict จะทำงาน

คุณควรพิจารณาเปลี่ยนกฎบางอย่างเป็น:

  1. เพิ่มอักขระพิเศษอื่น ๆ เช่น%, ^, (,), -, _, + และจุด ฉันกำลังเพิ่มอักขระพิเศษทั้งหมดที่คุณพลาดไปเหนือเครื่องหมายตัวเลขในคีย์บอร์ดของสหรัฐอเมริกา หลบหนีสิ่งที่ใช้ regex
  2. ทำรหัสผ่าน 8 ตัวขึ้นไป ไม่ใช่แค่จำนวนคงที่ 8

ด้วยการปรับปรุงข้างต้นและเพื่อความยืดหยุ่นและความสามารถในการอ่านได้มากขึ้นฉันจะแก้ไข regex ให้เป็น

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

คำอธิบายพื้นฐาน

(?=.*RULE){MIN_OCCURANCES,}     Each rule block is shown by (){}. The rule and number of occurrences can then be easily specified and tested separately, before getting combined

คำอธิบายโดยละเอียด

^                             start anchor
(?=.*[a-z]){3,}               lowercase letters. {3,} indicates that you want 3 of this group
(?=.*[A-Z]){2,}               uppercase letters. {2,} indicates that you want 2 of this group
(?=.*[0-9]){2,}               numbers. {2,} indicates that you want 2 of this group
(?=.*[!@#$%^&*()--__+.]){1,}   all the special characters in the [] fields. The ones used by regex are escaped by using the \ or the character itself. {1,} is redundant, but good practice, in case you change that to more than 1 in the future. Also keeps all the groups consistent
{8,}                          indicates that you want 8 or more
$                             end anchor

และสุดท้ายสำหรับวัตถุประสงค์ในการทดสอบที่นี่เป็นrobulinkกับ regex ข้างต้น


ขอบคุณ @ AFract ฉันใช้มันในรหัสของฉัน ฉันชอบการอ่านและทำซ้ำความสามารถสำหรับเมื่อคุณต้องกลับไปเปลี่ยนในอนาคตเช่นในกรณีของการเปลี่ยนแปลงนโยบายรหัสผ่าน :)
lsu_guy

0

สำหรับ PHP มันใช้งานได้ดี!

 if(preg_match("/^(?=(?:[^A-Z]*[A-Z]){2})(?=(?:[^0-9]*[0-9]){2}).{8,}$/", 
 'CaSu4Li8')){
    return true;
 }else{
    return fasle;
 }

ในกรณีนี้ผลลัพธ์จะเป็นจริง

ขอบคุณสำหรับ @ridgerunner


ทำไมไม่return preg_match("/^(?=(?:[^A-Z]*[A-Z]){2})(?=(?:[^0-9]*[0-9]){2}).{8,}$/", 'CaSu4Li8')?
aloisdg กำลังย้ายไปยัง codidact.com

0

ทางออกอื่น:

import re

passwordRegex = re.compile(r'''(
    ^(?=.*[A-Z].*[A-Z])                # at least two capital letters
    (?=.*[!@#$&*])                     # at least one of these special c-er
    (?=.*[0-9].*[0-9])                 # at least two numeric digits
    (?=.*[a-z].*[a-z].*[a-z])          # at least three lower case letters
    .{8,}                              # at least 8 total digits
    $
    )''', re.VERBOSE)

def userInputPasswordCheck():
    print('Enter a potential password:')
    while True:
        m = input()
        mo = passwordRegex.search(m) 
        if (not mo):
           print('''
Your password should have at least one special charachter,
two digits, two uppercase and three lowercase charachter. Length: 8+ ch-ers.

Enter another password:''')          
        else:
           print('Password is strong')
           return
userInputPasswordCheck()

0

รหัสผ่านจะต้องเป็นไปตามกฎความซับซ้อน 4 ข้อต่อไปนี้อย่างน้อย 3 ข้อ

[อย่างน้อย 1 ตัวอักษรตัวพิมพ์ใหญ่ (AZ) อย่างน้อย 1 ตัวอักษรตัวพิมพ์เล็ก (az) อย่างน้อย 1 หลัก (0-9) อย่างน้อย 1 ตัวอักษรพิเศษ - อย่าลืมรักษาพื้นที่เป็นตัวอักษรพิเศษด้วย]

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

สูงสุด 128 ตัวอักษร

อักขระที่เหมือนกันไม่เกิน 2 ตัวในหนึ่งแถว (เช่นไม่อนุญาต 111 ข้อ)

'^ (?!. (.) \ 1 {2}) ((? =. [az]) (? =. [AZ]) (? =. [0-9]) | (? =. [az] ) (? =. [AZ]) (? =. [^ a-zA-Z0-9]) | (? =. [AZ]) (? =. [0-9]) (? =. [^ a -zA-Z0-9]) | (? =. [az]) (? =. [0-9]) (? =. * [^ a-zA-Z0-9])) {10,127} $ '

(?!. * (.) \ 1 {2})

(? =. [az]) (? =. [AZ]) (? =. * [0-9])

(? =. [az]) (? =. [AZ]) (? =. * [^ a-zA-Z0-9])

(? =. [AZ]) (? =. [0-9]) (? =. * [^ a-zA-Z0-9])

(? =. [az]) (? =. [0-9]) (? =. * [^ a-zA-Z0-9])

. {10.127}


0

regex ทั้งหมดข้างต้นโชคไม่ดีสำหรับฉัน กฎพื้นฐานของรหัสผ่านที่คาดเดายากคือ

  • ควรมีตัวพิมพ์ใหญ่อย่างน้อย
  • ควรมีตัวอักษรขนาดเล็กอย่างน้อย
  • ควรมีตัวเลขอย่างน้อย
  • ควรมีอักขระพิเศษอย่างน้อยตัว
  • และความยาวต่ำสุด

ดังนั้น Best Regex จะเป็น

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

Regex ด้านบนมีความยาวต่ำสุด 8 คุณสามารถเปลี่ยนจาก {8,} เป็น { any_number ,}

การปรับเปลี่ยนในกฎ?

ขอบอกว่าคุณต้องการขั้นต่ำxตัวอักษรตัวอักษรขนาดเล็กYตัวอักษรตัวพิมพ์ใหญ่, Zตัวเลขตัวอักษรรวมความยาวต่ำสุดW จากนั้นลองด้านล่าง regex

^(?=.*[a-z]{x,})(?=.*[A-Z]{y,})(?=.*[0-9]{z,})(?=.*[!@#\$%\^&\*]).{w,}$

หมายเหตุ:เปลี่ยนx , y , z , wใน regex

แก้ไข: อัปเดตคำตอบ regex

แก้ไข 2: เพิ่มการแก้ไข


regex ของคุณตรงกัน12345678คุณแน่ใจหรือว่าเป็นรหัสผ่านที่คาดเดายาก ? โปรดลอง regex ของคุณก่อนโพสต์
โตโต้

ดีกว่า แต่ไม่ตอบคำถามพวกเขาต้องการความยาว 1) 8 ตัวอักษร 2) 2 ตัวอักษรในตัวพิมพ์ใหญ่ 3) 1 อักขระพิเศษ (! @ # $ & *) 4) 2 ตัวเลข (0-9) 5) 3 ตัวอักษรในกรณีที่ต่ำกว่า
โตโต้

@Toto คุณช่วยแบ่งปันความคิดของคุณตอนนี้ได้ไหม?
Juned Khatri

regex ของคุณไม่ได้คำนึงถึงว่าตัวอักษรตัวพิมพ์ใหญ่บังคับ 2 ตัวสามารถแยกออกจากกันด้วยตัวอักษรอื่นคำพูดเดียวกันสำหรับตัวพิมพ์เล็กและตัวเลข คำตอบที่ถูกต้องคือคำตอบที่ได้รับการยอมรับ
โตโต้
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.