Daha önce verilen yanıtların tümü, her gereksinim için ayrı bir ilerleme kullanmak üzere aynı (doğru) tekniği kullanır. Ancak, parolayı gerçekten kullanacak arka uca bağlı olarak, birkaç verimsizlik ve potansiyel olarak büyük bir hata içerirler.
Kabul edilen yanıttan normal ifadeyle başlayacağım:
^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\S+$).{8,}$
Öncelikle, Java desteklediğinden \A
ve \z
ben bunları tüm dizenin doğrulandığından emin olmak için kullanmayı tercih ediyorum Pattern.MULTILINE
. Bu, performansı etkilemez, ancak normal ifadeler geri dönüştürüldüğünde hataları önler.
\A(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\S+$).{8,}\z
Parolanın boşluk içermediğinin kontrol edilmesi ve minimum uzunluğunun kontrol edilmesi , izin verilen karakterleri sınırlayan {8,}
stenoya değişken nicelik belirteci koyarak tek seferde tümü kullanılarak yapılabilir \S
:
\A(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])\S{8,}\z
Sağlanan parola bir boşluk içeriyorsa, tüm kontroller, yalnızca alanda son kontrolün başarısız olması için yapılacaktır. Bu, tüm noktaları aşağıdakilerle değiştirerek önlenebilir \S
:
\A(?=\S*[0-9])(?=\S*[a-z])(?=\S*[A-Z])(?=\S*[@#$%^&+=])\S{8,}\z
Nokta yalnızca herhangi bir karaktere gerçekten izin vermek istiyorsanız kullanılmalıdır. Aksi takdirde, normal ifadenizi yalnızca gerçekten izin verilen karakterlerle sınırlamak için (olumsuzlanmış) bir karakter sınıfı kullanın. Bu durumda çok az fark yaratsa da, başka bir şey daha uygun olduğunda noktayı kullanmamak çok iyi bir alışkanlıktır. Geliştirici noktadan daha uygun bir şey kullanamayacak kadar tembel olduğu için çok fazla geri dönüş vakası görüyorum .
İlk testlerin parolanın ilk yarısında uygun bir karakter bulma ihtimali yüksek olduğundan, tembel bir nicelik belirteci daha verimli olabilir:
\A(?=\S*?[0-9])(?=\S*?[a-z])(?=\S*?[A-Z])(?=\S*?[@#$%^&+=])\S{8,}\z
Ama şimdi gerçekten önemli konuya gelelim: cevapların hiçbiri, orijinal sorunun ASCII'de düşünen biri tarafından yazılmış gibi göründüğünden bahsetmiyor. Ancak Java'da dizeler Unicode'dur. Şifrelerde ASCII olmayan karakterlere izin verilir mi? Eğer öyleyse, yalnızca ASCII boşluklarına izin verilmiyordur veya tüm Unicode boşlukları hariç tutulmalıdır.
Varsayılan olarak \s
yalnızca ASCII beyaz boşlukla eşleşir, bu nedenle tersi \S
tüm Unicode karakterleriyle (beyaz boşluk veya değil) ve tüm boşluk olmayan ASCII karakterlerle eşleşir. Unicode karakterlere izin veriliyorsa ancak Unicode boşlukları yoksa, Unicode boşluklarını dışlamak için UNICODE_CHARACTER_CLASS
bayrak belirtilebilir \S
. Unicode karakterlere izin verilmiyorsa, boşluk veya kontrol karakteri olmayan tüm ASCII karakterlerini eşleştirmek [\x21-\x7E]
yerine kullanılabilir \S
.
Bu da bizi bir sonraki potansiyel soruna getiriyor: kontrol karakterlerine izin vermek istiyor muyuz? Düzgün bir normal ifade yazmanın ilk adımı, neyi eşleştirmek istediğinizi ve neyi eşleşmediğinizi tam olarak belirlemektir. Teknik olarak% 100 doğru tek cevap, sorudaki parola spesifikasyonunun belirsiz olmasıdır, çünkü kontrol karakterleri veya ASCII olmayan karakterler gibi belirli karakter aralıklarına izin verilip verilmediğini belirtmez.