Regex untuk memvalidasi kekuatan kata sandi


142

Kriteria kekuatan kata sandi saya adalah sebagai berikut:

  • Panjang 8 karakter
  • 2 huruf dalam Huruf Besar
  • 1 Karakter Khusus (!@#$&*)
  • 2 angka (0-9)
  • 3 huruf dalam Huruf Kecil

Dapatkah seseorang tolong beri saya regex untuk hal yang sama. Semua ketentuan harus dipenuhi dengan kata sandi.


2
Apakah Anda benar-benar mau mempercayai langkah-langkah keamanan kata sandi Anda ke Internet pada umumnya?
Borealid

12
@ Borore: memublikasikan kebijakan kata sandi Anda biasanya tidak berdampak signifikan terhadap keamanan Anda. Jika ya, maka kebijakan Anda buruk ("Hanya passworddan hello123kata sandi yang valid!").
Joachim Sauer

3
@ Joachim Sauer: Bukan itu yang saya maksud. Yang saya maksudkan adalah bahwa poster itu mungkin hanya akan mempercayai regex apa pun yang diterimanya. Bukan ide yang bagus.
Borealid

3
Sebenarnya regex ini akan berada dalam kode layanan, saya akan menguji untuk kasus-kasus berbeda tidak secara membuta mempercayainya :)
Ajay Kelkar

9
Aturan kata sandi yang kompleks biasanya tidak akan menghasilkan kata sandi yang lebih aman, yang penting hanya panjang minimum. Orang tidak dapat mengingat banyak kata sandi yang kuat, dan aturan semacam itu dapat mengganggu skema kata sandi yang baik. Orang-orang bisa menjadi sangat inventif untuk mem-bypass aturan semacam itu, misalnya dengan menggunakan kata sandi yang lemah seperti "Kata Sandi-2014". Seringkali Anda berakhir dengan kata sandi yang lebih lemah daripada kata sandi yang lebih kuat.
martinstoeckli

Jawaban:


428

Anda dapat melakukan pemeriksaan ini menggunakan pernyataan pandangan ke depan yang positif:

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

Tautan rubular

Penjelasan:

^                         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
Bagi siapa saja yang ingin panjang setidaknya n, ganti .{8}dengan.{n,}
NullUserException

14
+1 untuk penjelasan lengkap. Aturan kata sandi saya berbeda tetapi berdasarkan jawaban Anda, saya dapat mengadaptasi regex.
Morvael

14
Terima kasih telah menjelaskan apa yang terjadi di regex. Ini berfungsi sebagai contoh pembelajaran yang bagus bagi kita yang belum pernah benar-benar memahami sintaksis.

4
Saya juga menghargai penjelasan dari regex. Berkali-kali saya menggunakan regex kompleks yang saya temukan, tanpa benar-benar memahami apa yang sedang terjadi.
Nicholas Smith

4
Pola yang bagus, saya bertanya-tanya mengapa tidak menggunakan pembilang? Setidaknya 1 khusus, 1 angka, 1 karakter khusus, 8 karakter: ^ (? =. * ([AZ]) {1,}) (? =. * [! @ # $ & *] {1,}) ( ? =. * [0-9] {1,}) (? =. * [Az] {1,}). {8.100} $
RockOnGom

11

Anda dapat menggunakan pandangan positif nol panjang untuk menentukan masing-masing kendala Anda secara terpisah:

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

Jika mesin regex Anda tidak mendukung \pnotasi dan ASCII murni sudah cukup, maka Anda dapat mengganti \p{Lu}dengan [A-Z]dan \p{Ll}dengan [a-z].


8

Jawaban yang diberikan di atas sempurna tetapi saya menyarankan untuk menggunakan beberapa regex yang lebih kecil daripada yang besar.
Membagi regex panjang memiliki beberapa keunggulan:

  • kemudahan untuk menulis dan membaca
  • kemudahan untuk debug
  • kemudahan untuk menambah / menghapus bagian dari regex

Umumnya pendekatan ini menjaga kode mudah dipelihara .

Karena itu, saya membagikan sepotong kode yang saya tulis di Swift sebagai contoh:

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 []
        }
    }
}

Juga, ketika menggunakan regex kompleks seperti di atas, sangat mudah untuk membuka diri Anda ke pengulangan bencana ( regular-expressions.info/catastrophic.html ). Ini bisa tanpa disadari sampai suatu hari server Anda hang dengan CPU 100% karena pengguna menggunakan kata sandi "aneh". Contoh: ^ ([a-z0-9] +) {8,} $ (dapatkah Anda melihat kesalahannya?)
aKzenT

5

Saya sarankan menambahkan

(?!.*pass|.*word|.*1234|.*qwer|.*asdf) exclude common passwords

1

solusi codaddict berfungsi dengan baik, tetapi yang ini sedikit lebih efisien: (sintaks 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)

Kelas karakter yang dinegasikan mengkonsumsi semuanya hingga karakter yang diinginkan dalam satu langkah, membutuhkan nol mundur. (Solusi titik bintang berfungsi dengan baik, tetapi membutuhkan beberapa langkah mundur.) Tentu saja dengan string target pendek seperti kata sandi, peningkatan efisiensi ini akan diabaikan.


Bisakah Anda memeriksa apakah itu benar? Saya ragu karena membuka braket putaran di baris pertama antara triple doublequote dan tanda tanya. Saya bisa melihat bahwa komentar Python (hash) nanti. Saya tidak dapat melihat braket bundar penutupan koresponden dekat jangkar ujung (tanda dolar). Harus menyebutkan saya bukan profy profex.
lospejos

@ lospejos - # bukan awal dari komentar satu baris reguler. Hash ini adalah bagian dari grup komentar yang dimulai dengan a (?#dan diakhiri dengan a ). Tidak ada parens tidak seimbang di regex ini.
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

Solusi @ codaddict akan berfungsi.

Anda juga harus mempertimbangkan untuk mengubah beberapa aturan Anda menjadi:

  1. Tambahkan lebih banyak karakter khusus yaitu%, ^, (,), -, _, +, dan titik. Saya menambahkan semua karakter khusus yang Anda lewatkan di atas tanda angka di keyboard AS. Melarikan diri dari yang menggunakan regex.
  2. Buat kata sandi 8 atau lebih karakter. Bukan hanya angka statis 8.

Dengan peningkatan di atas, dan untuk lebih fleksibel dan mudah dibaca, saya akan memodifikasi regex menjadi.

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

Penjelasan Dasar

(?=.*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

Penjelasan detail

^                             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

Dan terakhir, untuk tujuan pengujian di sini adalah robulink dengan regex di atas


Terima kasih @ Ort. Saya menggunakannya dalam kode saya. Saya suka keterbacaan dan kemampuan pengulangan, karena ketika Anda harus kembali dan mengubahnya di masa depan yaitu dalam hal perubahan kebijakan kata sandi :)
lsu_guy

0

Untuk PHP, ini berfungsi dengan baik!

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

dalam hal ini hasilnya benar

Thsks for @ridgerunner


mengapa tidak return preg_match("/^(?=(?:[^A-Z]*[A-Z]){2})(?=(?:[^0-9]*[0-9]){2}).{8,}$/", 'CaSu4Li8')?
aloisdg pindah ke codidact.com

0

Solusi lain:

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

Kata sandi harus memenuhi setidaknya 3 dari 4 aturan kompleksitas berikut,

[setidaknya 1 karakter huruf besar (AZ) setidaknya 1 karakter huruf kecil (az) minimal 1 digit (0-9) setidaknya 1 karakter khusus - jangan lupa memperlakukan ruang sebagai karakter khusus juga]

setidaknya 10 karakter

paling banyak 128 karakter

tidak lebih dari 2 karakter identik berturut-turut (mis., 111 tidak diizinkan)

'^ (?!. (.) \ 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

Sayangnya semua regex di atas tidak bekerja untuk saya. Aturan dasar kata sandi yang kuat adalah

  • Harus mengandung setidaknya huruf kapital
  • Harus mengandung setidaknya surat kecil
  • Harus mengandung setidaknya angka
  • Harus mengandung setidaknya karakter khusus
  • Dan panjang minimum

Jadi, Regex Terbaik adalah

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

Regex di atas memiliki panjang minimum 8. Anda dapat mengubahnya dari {8,} ke { any_number ,}

Modifikasi dalam aturan?

mari kita katakan Anda ingin minimum x karakter huruf kecil, y karakter huruf kapital, z nomor karakter, total panjang minimum w . Kemudian coba di bawah regex

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

Catatan: Ubah x , y , z , w di regex

Sunting: Jawaban regex yang diperbarui

Edit2: Menambahkan modifikasi


Regex Anda cocok 12345678, Anda yakin itu kata sandi yang kuat ? Silakan, coba regex Anda sebelum memposting.
Toto

Itu lebih baik tetapi tidak menjawab pertanyaan, mereka ingin 1) panjang 8 karakter. 2) 2 huruf dalam Huruf Besar. 3) 1 Karakter Khusus (! @ # $ & *). 4) 2 angka (0-9). 5) 3 huruf dalam Huruf Kecil.
Toto

@Toto Bisakah Anda berbagi pemikiran Anda sekarang?
Juned Khatri

Regex Anda tidak memperhitungkan bahwa 2 huruf besar wajib bisa dipisahkan dengan karakter lain, komentar yang sama untuk huruf kecil dan digit. Jawaban yang valid adalah jawaban yang telah diterima.
Toto
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.