Şifrenin "1 büyük harf, 1 özel karakter, alfanümerik karakterler içeren 8 karakter" olup olmadığını kontrol etmek için normal ifade


102

Bunu kontrol etmek için normal bir ifade istiyorum

bir parola, bir büyük harf, bir özel karakter ve alfanümerik karakterler içeren sekiz karakterden oluşmalıdır.

Ve işte bir büyük harf, bir küçük harf ve bir sayı veya özel karakter içeren sekiz karakter için olan doğrulama ifadem.

(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$"

Bir büyük harf, bir özel karakter ve alfanümerik karakterler içeren sekiz karakterden oluşan bir şifre için nasıl yazabilirim?


26
Bunun için neden normal bir ifadeye ihtiyacınız var? Gereksinimlerinize uyan eksiksiz bir düzenli ifade çok uzun ve karmaşık olacaktır. Kısıtlamalarınızı C # kodunda yazmak daha kolaydır.
Greg Hewgill

33
Parolanın, güçlü bir parola için kusurlu bir proxy olan bazı keyfi kuralları karşılayıp karşılamadığını kontrol etmek yerine, güçlü bir parola denetlemeyi düşündünüz mü? Parola verildiğinde gücünü belirleyecek çok sayıda kitaplık ve program vardır.
Wayne Conrad

4
@GregHewgill Eğer yapabilseydim yorumunuza olumlu oy verirdim :-) Bu başka bir durum gibi görünüyor: "Eğer sahip olduğunuz tek şey bir çekiçse, her şey bir çivi gibi görünmeye başlar".
Christian.K

3
İhtiyacınız mı tam bir büyük harf / özel karakter veya en azından birinin?
mmdemirbas

4
Kullanıcının gereksinimi ile, kullanıcınızın uygulama detaylarını dikte ettiğini mi kastediyorsunuz? O halde belki de bunu kendileri kodlamalılar. Dürüst olmak gerekirse, bir kuralla eşleşen her karakter için uygun sayaçları artırarak sayaçları yeni oluşturup her karakteri tek tek kontrol etseniz, sürdürmenin ve anlamanın daha kolay olacağını düşünüyorum. Teknik açıdan bakıldığında, kimseyi etkileyecek bir şey değil, ama neden işleri hataya açık ve güncellenmesi zor bir şeyle karmaşıklaştıralım?

Yanıtlar:


132

Peşinde olduğunuz normal ifade büyük olasılıkla çok büyük olacak ve özellikle normal ifadelere aşina olmayan insanlar için sürdürülmesi gereken bir kabus olacaktır.

Normal ifadenizi parçalayıp her seferinde bir parça yapmanın daha kolay olacağını düşünüyorum. Yapması biraz daha zaman alabilir, ancak bunu sürdürmenin ve hata ayıklamanın daha kolay olacağından oldukça eminim. Bu aynı zamanda, Invalid Passwordkullanıcı deneyimini iyileştirmesi gereken (sadece dışında ) kullanıcılarınıza daha yönlendirilmiş hata mesajları sağlamanıza olanak tanır .

Gördüğüm kadarıyla normal ifadede oldukça akıcısınız, bu yüzden ihtiyacınız olan şeyi yapmanız için size normal ifadeleri vermenin boşuna olacağını varsayıyorum.

Yorumunuzu görünce, bu şekilde devam ederdim:

  • Sekiz karakter uzunluğunda olmalıdır: Bunun için bir normal ifadeye ihtiyacınız yoktur. .LengthMülkü kullanmak yeterli olmalıdır.

  • Bir büyük harf dahil: [A-Z]+Normal ifadeyi kullanabilirsiniz . Dize en az bir büyük harf içeriyorsa, bu normal ifade ortaya çıkar true.

  • Bir özel karakter: \WHarf veya sayı olmayan herhangi bir karakterle eşleşecek olanı kullanabilir veya başka [!@#]bir özel karakter listesi belirtmek için buna benzer bir şey kullanabilirsiniz . Not gibi bu karakterlerin olsa $, ^, (ve )onlar şöyle kaçtı gerekir, böylece düzenli ifade dilinde özel karakterler: \$. Kısacası \W,.

  • Alfasayısal karakterler: Kullanmak, \w+herhangi bir harf, sayı ve alt çizgi ile eşleşmelidir.

Daha fazla bilgi için bu eğiticiye bir göz atın .


2
bunu yazmadım kendim google'dan aldım sevgili arkadaşım
Rania Umair

4
@RaniaUmair: Yorumunuzun benim açımdan kanıtladığını düşünüyorum. Bunu da belirttiğim gibi parçalamanızı tavsiye ederim.
npinti

35
+1 Regex güçlüdür, ancak evrendeki herhangi bir sorunu çözmesi amaçlanmamıştır
Cristian Lupascu

@ w0lf: Daha fazla katılamadım. Regex güçlüdür, ancak çok hızlı karmaşıklaşır, bu yüzden basit tutması daha iyi olur.
npinti

bana yardım edebilir i herhangi bir şey olabilir en azından bir numara ve maksimum 3 diğer charecters kabul bir RegX ihtiyaç
Lijo

107
(                   # Start of group
    (?=.*\d)        #   must contain at least one digit
    (?=.*[A-Z])     #   must contain at least one uppercase character
    (?=.*\W)        #   must contain at least one special symbol
       .            #     match anything with previous condition checking
         {8,8}      #        length is exactly 8 characters
)                   # End of group

Tek satırda:

((?=.*\d)(?=.*[A-Z])(?=.*\W).{8,8})

2019-05-28'i düzenleyin:

Giriş dizesinin tamamını eşleştirmeniz gerekir. Dolayısıyla, normal ifadeyi içine alabilir ^ve $yanlışlıkla kısmi eşleşmelerin tüm girdiyle eşleştiğini varsaymayı önlemek için:

^((?=.*\d)(?=.*[A-Z])(?=.*\W).{8,8})$

Kaynaklar:


58
12 karakterden oluştuğu için
mmdemirbas

bir koşul daha rakamla başlamamalı bunu nasıl yapabilirim?
Lijo

7
8 karakteri eşleştirmek için {8} kullanarak kısaltabilirsiniz
Angelo Tricarico

$ 1eerrrrrrr ile eşleşiyor .. büyük harfi yok.
Shilpi Jaiswal

@ShilpiJaiswal Ya büyük / küçük harfe duyarlı olmayan eşleştirme için bir bayrak kullanıyorsunuz veya "eşleşme" yerine "bul" yapıyorsunuz. Eğer Tüm giriş dizesini eşleşen sağlamak için, aralarında regex koyabilirsiniz.Eğer ^ve $. Deneyin:^((?=.*\d)(?=.*[A-Z])(?=.*\W).{8,8})$
mmdemirbas

35

Çok fazla cevap .... hepsi kötü!

Normal ifadelerin bir AND operatörü yoktur, bu nedenle geçerlilik bir VE başka bir şey VE başka bir şey tarafından tanımlandığında, geçerli parolalarla eşleşen bir normal ifade yazmak oldukça zordur ...

Ama, düzenli ifadeler yapmak yani sadece DeMorgan teoremini uygulamak ve eşleşen bir düzenli ifade yazmak, bir OR operatörü sahip geçersiz şifreleri.

az 8 karakterli şey VEYA numarası olmayan bir şey VEYA hiçbir büyük harf ile bir şey VEYA hiçbir özel karakterler ile bir şey

Yani:

^(.{0,7}|[^0-9]*|[^A-Z]*|[a-zA-Z0-9]*)$

Bununla eşleşen herhangi bir şey varsa, bu geçersiz bir paroladır.


3
OP tam olarak 8 karakter istiyorsa, eklemeniz gerekir |.{9,}. Konsept için +1
Daniel

Soru için harika ve basit bir çözüm, ancak tek bir düzenli ifadenin gerçek sorun için en uygun ifade olmadığına katılıyorum.
Siderite Zackwehdex

1
Düzenli ifadeler do sahip VE operatörler, bunlar ileri yönlü / geriye bakan iddialarını deniyor.
nispeten_random

13

Cevap, normal bir ifade kullanmamaktır. Bu setler ve sayma.

Normal ifadeler düzen hakkındadır.

Bir programcı olarak hayatınızda, mantıklı olmayan birçok şey yapmanız istenecektir. Daha derine inmeyi öğrenin. Sorunun ne zaman yanlış olduğunu öğrenin.

Soru (normal ifadelerden söz ettiyse) yanlış.

Sözde kod (geç, çok fazla dil arasında geçiş yapılıyor):

if s.length < 8:
    return False
nUpper = nLower = nAlphanum = nSpecial = 0
for c in s:
    if isUpper(c):
        nUpper++
    if isLower(c):
        nLower++
    if isAlphanumeric(c):
        nAlphanum++
    if isSpecial(c):
        nSpecial++
return (0 < nUpper) and (0 < nAlphanum) and (0 < nSpecial)

Bahse girerim yukarıdaki kodu neredeyse anında okuyup anladınız. Bahse girerim normal ifadeyle çok daha uzun sürdünüz ve doğru olduğundan daha az eminsiniz. Normal ifadeyi genişletmek risklidir. Hemen yukarıyı genişletti, çok daha az.

Ayrıca sorunun kesin olarak ifade edildiğine dikkat edin. Karakter seti ASCII veya Unicode veya ?? Soruyu okurken tahminim en az bir küçük harfli karakterin varsayılmasıdır. Bu yüzden, varsayılan son kuralın şöyle olması gerektiğini düşünüyorum:

return (0 < nUpper) and (0 < nLower) and (0 < nAlphanum) and (0 < nSpecial)

(Şapkaları güvenlik odaklı yapmak, bu gerçekten can sıkıcı / kullanışlı olmayan bir kuraldır.)

Sorunun ne zaman yanlış olduğunu bilmeyi öğrenmek, akıllı cevaplardan çok daha önemlidir. Yanlış soruya akıllıca cevap vermek neredeyse her zaman yanlıştır.


2
Katılıyorum. Ne kadar çok insanla çalışırsanız, bazı regexp uygulamalarının cevaplar oldukça açık olmasına rağmen, kodun o kadar okunabilir olması gerekir
Nicola Peluchetti

Sizin gibi bazı kullanıcıların, Regex'in her zaman uygulamak için daha iyi bir çözüm olmadığını ve bazen basit programlamanın daha okunaklı olduğunu söyleme cesaretine sahip olmasını seviyorum.
schlebe

12

Okunabilir / sürdürülebilir bir normal ifadeyle bunun nasıl yapılabileceğine bir örnek olarak.

Daha uzun bir normal RegexOptions.IgnorePatternWhitespaceifade için, daha iyi okunabilirlik için ifadede her zaman boşluklara ve yorumlara izin vermeyi kullanmalısınız .

String[] passwords = { "foobar", "Foobar", "Foobar1", "Fooobar12" };

foreach (String s in passwords) {

    Match password = Regex.Match(s, @"
                                      ^              # Match the start of the string
                                       (?=.*\p{Lu})  # Positive lookahead assertion, is true when there is an uppercase letter
                                       (?=.*\P{L})   # Positive lookahead assertion, is true when there is a non-letter
                                       \S{8,}        # At least 8 non whitespace characters
                                      $              # Match the end of the string
                                     ", RegexOptions.IgnorePatternWhitespace);

    if (password.Success) {
        Console.WriteLine(s + ": valid");
    }
    else {
        Console.WriteLine(s + ": invalid");
    }
}

Console.ReadLine();

Bu, lookahead assertiontüm kısıtlamayı tek bir normal ifadede kapsayacak şekilde bir "ve" kalıbı olarak kötüye kullanmanın en iyi yoludur . Daha fazla kısıtlama için çalışır ve bazı kısıtlamaların konfigürasyon tarafından etkinleştirilmesi / devre dışı bırakılması gerektiğinde kolayca oluşturulabilir.
dognose

2
Unicode kategorilerinin kullanımı mükemmel bir fikirdir. Dünya ASCII'den daha geniştir!
Walter Tross

1

Yalnızca bir büyük harfe ve özel karaktere ihtiyacınız varsa, bu işe yaramalıdır:

@"^(?=.{8,}$)(?=[^A-Z]*[A-Z][^A-Z]*$)\w*\W\w*$"

AAaaaaaaa#Bu ifadeye göre dizi tamam değil
Cristian Lupascu

3
Eh, 10, 8 karakter uzunluğunda değil ve birden fazla büyük harf içeriyor, bu yüzden başarısız olmalı ...
user1096188

4
Haklısın, soruda bunu söylüyor. Bu kuralların "tam olarak bir büyük harf" yerine "en az bir büyük harf" olduğunu düşündüm . Yine de OP'nin istediği şeyin bu olduğundan emin değilim.
Cristian Lupascu


0

Bu soru viral olmaya başladı ve birçok ilginç öneri ortaya çıktı.

Evet, elle yazmak zordur. Bu yüzden daha kolay bir çözüm, bir şablon kullanmaktır. Sonuçta ortaya çıkan normal ifade en uygun olmasa da, sürdürülmesi ve / veya değiştirilmesi daha kolay olacaktır ve kullanıcının sonuç üzerinde daha iyi bir kontrolü olacaktır. Bir şeyleri gözden kaçırmışım olabilir, bu nedenle herhangi bir yapıcı eleştiri yardımcı olacaktır.

Bu bağlantılar ilginç olabilir: Bir dizede herhangi bir sırada en az 2 rakamla 2 harfle eşleştirin , Normal İfade Dili , Yakalama grupları

(?=(?:.*?({type})){({count})})SO'da gördüğüm tüm normal ifadeleri temel alarak bu şablonu kullanıyorum . Bir sonraki adım, gerekli kalıbı ( number, special character...) değiştirmek ve uzunluk için yapılandırma eklemek.

PasswordRegexGenerator.cs normal ifadesini oluşturmak için küçük bir sınıf hazırladım Bir örnek:

string result = new PasswordRegexGenerator ( )
        .UpperCase ( 3, -1 )    // ... {3,}
        .Number ( 2, 4 )        // ... {2,4}
        .SpecialCharacter ( 2 ) // ... {2}
        .Total ( 8,-1 )
        .Compose ( );

/// <summary>
/// Generator for regular expression, validating password requirements.
/// </summary>
public class PasswordRegexGenerator
{
    private string _elementTemplate = "(?=(?:.*?({type})){({count})})";

    private Dictionary<string, string> _elements = new Dictionary<string, string> {
        { "uppercase", "[A-Z]" },
        { "lowercase", "[a-z]" },
        { "number", @"\d" },
        { "special", @"\W" },
        { "alphanumeric", @"\w" }
    };

    private StringBuilder _sb = new StringBuilder ( );

    private string Construct ( string what, int min, int max )
    {
        StringBuilder sb = new StringBuilder ( _elementTemplate );
        string count = min.ToString ( );

        if ( max == -1 )
        {
            count += ",";
        }
        else if ( max > 0 )
        {
            count += "," + max.ToString();
        }

        return sb
            .Replace ( "({type})", what )
            .Replace ( "({count})", count )
            .ToString ( );
    }

    /// <summary>
    /// Change the template for the generation of the regex parts
    /// </summary>
    /// <param name="newTemplate">the new template</param>
    /// <returns></returns>
    public PasswordRegexGenerator ChangeRegexTemplate ( string newTemplate )
    {
        _elementTemplate = newTemplate;
        return this;
       }

    /// <summary>
    /// Change or update the regex for a certain type ( number, uppercase ... )
    /// </summary>
    /// <param name="name">type of the regex</param>
    /// <param name="regex">new value for the regex</param>
    /// <returns></returns>
    public PasswordRegexGenerator ChangeRegexElements ( string name, string regex )
    {
        if ( _elements.ContainsKey ( name ) )
        {
            _elements[ name ] = regex;
        }
        else
        {
            _elements.Add ( name, regex );
        }
        return this;
    }

    #region construction methods 

    /// <summary>
    /// Adding number requirement
    /// </summary>
    /// <param name="min"></param>
    /// <param name="max"></param>
    /// <returns></returns>
    public PasswordRegexGenerator Number ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "number" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator UpperCase ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "uppercase" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator LowerCase ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "lowercase" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator SpecialCharacter ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "special" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator Total ( int min, int max = 0 )
    {
        string count = min.ToString ( ) + ( ( max == 0 ) ? "" : "," + max.ToString ( ) );
        _sb.Append ( ".{" + count + "}" );
        return this;
    }

    #endregion

    public string Compose ()
    {
        return "(" + _sb.ToString ( ) + ")";
    }
}

0

Doğrulama için aşağıdaki sınıfı kullanabilirsiniz:

public class PasswordValidator{

  private Pattern pattern;
  private Matcher matcher;

  private static final String PASSWORD_PATTERN =
          "((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%]).{6,20})";

  public PasswordValidator(){
      pattern = Pattern.compile(PASSWORD_PATTERN);
  }

  /**
   * Validate password with regular expression
   * @param password password for validation
   * @return true valid password, false invalid password
   */
  public boolean validate(final String password){

      matcher = pattern.matcher(password);
      return matcher.matches();

  }
}

burada 6 ve 20 parola için minimum ve maksimum uzunluktur.


0
  • En az 8 karakter içeriyorsa, önce tüm parolayı eşleştirmek için geriye dönük olmayan bir ifade kullanın (bu şekilde, uzun, ancak geçersiz parolalar için kombinasyon patlaması olmaz): (?>{8,})
  • Tüm gerekli karakterlerin (VE koşulları) varlığını kontrol etmek için arkaya bakma iddialarını kullanın. (?<=...)
  • En az bir büyük harf karakteri: (?<=\p{Lu}.*)
  • En az bir özel karakter (biraz belirsiz, ancak kelime kullanmayalım): (?<=\W.*)
  • En az bir alfasayısal karakter (: (?<=\w.*)

Özetlenmiş:

(?>.{8,})(?<=\p{Lu}.*)(?<=\W.*)(?<=\w.*)


0

En iyisi, her şey için normal ifade kullanmamaktır. Bu gereksinimler çok hafiftir. Ölçütleri / doğrulamayı kontrol etmek için CPU-bilge dizge işlemleri, regex'ten çok daha ucuz ve daha hızlıdır!


0

var regex =/^(?=.*\d)(?=.*[!@#$%^&*])(?=.*[a-z])(?=.*[A-Z]).{8,64}$/;

 
function test() {

 if(regex.test(document.getElementById("txtPassword").value)===false)
 {
 alert("Min 6,Max 64,At Least One Uppercase Character,One Lowercase Character,One Numeric Value And One Special Character(!@#$%^&*) Required ");
 }
 else
 {
 alert("Success");
 }
}
<input type="text" id="txtPassword" />
<button id="testBtn" onclick=test()>CheckPassword</button>


Bu kod parçacığı sorunu çözebilir ancak soruyu neden veya nasıl yanıtladığını açıklamaz. Lütfen kodunuz için bir açıklamaya yer gerçekten Yayınınızla kalitesini artırmak için yardımcı olarak,. Gelecekte okuyucular için soruyu yanıtladığınızı ve bu kişilerin kod önerinizin nedenlerini bilmeyebileceklerini unutmayın. Daha fazla oy ve itibar elde etmek için bu yanıtı iyileştirmek için düzenle düğmesini kullanabilirsiniz !
Brian Tompsett -汤莱恩

-2
/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}$/

15
Sorunuzu düzenlemenizi ve bazı açıklamalar eklemenizi öneririm. Yalnızca kod yanıtları bazen yeterince iyidir, ancak kod + açıklama yanıtları her zaman daha iyidir
Barranka
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.