2016-01-28 7 views
3

В настоящее время я работаю с регулярным выражением, которое я создал для пароля.Regex - только ОДИН специальный char

Это должны соблюдать эти условия:

  • 8 символов
  • По крайней мере один MAJ (AZ)
  • По крайней мере один мин (AZ)
  • По крайней мере, одну цифру (0-9)
  • Один специальный символ из следующих функций:,:; '@ # $%^& * _ + = |() {} -/\
  • запрещать следующие символы.! [?]: <> `

Вот регулярное выражение:

(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[.,:;'[email protected]#$%^&*_+=|(){}[?\-\]\/\\])(?!.*[<>`]).{8} 

Все работает отлично, но теперь, я хочу, чтобы принять только один специальный символ.

Я искал и пробовал много вещей (например, с {1} в конце группы), но это не работает вообще! Результаты, подобные Aa1 ;; aaa все еще соответствуют ..

Может ли кто-нибудь сказать мне, как я могу это сделать?

+4

** На боковой ноте: ** Пожалуйста, не ограничивайте пользователей таким образом. Некоторым пользователям не нравится, когда вы вынуждены использовать невозможное для запоминания паролей. Вы можете добавить предупреждение «слабый пароль», если хотите, но запретить его просто разочаровывает. (Также, говоря, что пароль, подобный «somelargesentencatatishardtobruteforce», слаб, просто тупой). –

+2

Ограничение пользователей, как это ** уменьшить ** безопасность, потому что он отвергает надежные пароли и затрудняет использование генераторов паролей. – Tom

+0

Это длинное и ужасное регулярное выражение. Вы рассматривали вопрос о применении критериев проверки отдельно, так что у вас есть хотя бы шанс когда-либо понять его, когда вы вернетесь к нему через 6 месяцев? – Sobrique

ответ

1

насчет:

^(?=.{8}$)(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?!.*[<>`])([^.,:;'[email protected]#$%^&*_+=|(){}[?\-\]\/\\]*)[.,:;'[email protected]#$%^&*_+=|(){}[?\-\]\/\\](?1)$

DEMO

Это проверить длину с опережающим просмотром, то делает, что он имеет только один специальный символ, с чем-то другом до и после того, как

(?1) - ссылка на образец 1-й группы, вы можете заменить его [^.,:;'[email protected]#$%^&*_+=|(){}[?\-\]\/\\]* Если вы хотите или не поддержали свой инструмент

DEMO

Или, сохранив при этом свой первоначальный синтаксис:

(?=.*[A-Z]) (?=.*[a-z]) (?=.*[0-9]) (?!.*[<>`]) (?=[^.,:;'[email protected]#$%^&*_+=|(){}[?\-\]\/\\]* [.,:;'[email protected]#$%^&*_+=|(){}[?\-\]\/\\] [^.,:;'[email protected]#$%^&*_+=|(){}[?\-\]\/\\]*$ ) .{8}$

Вот уплотненная версия: (?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?!.*[<>`])(?=[^.,:;'[email protected]#$%^&*_+=|(){}[?\-\]\/\\]*[.,:;'[email protected]#$%^&*_+=|(){}[?\-\]\/\\][^.,:;'[email protected]#$%^&*_+=|(){}[?\-\]\/\\]*$).{8}$

DEMO

+0

Я думаю, что это действительно хороший пример того, почему regex очень мощный, но shouldn Нельзя использовать для каждой работы! – Sobrique

+1

@Sobrique Он отвечает на вопрос OP действительно, но в качестве комментариев, упомянутых выше: ограничение psw - это плохая идея; У меня был опыт сам быть застрявшим на странице регистрации без понятия, что не так => это был psw: S – Enissay

+0

Согласовано - это так. И регулярное выражение - очень мощный инструмент. Это просто неправильно (на мой взгляд) для этой конкретной работы – Sobrique

2

Действительно - я бы не сделать это. Первые правила фальшивых паролей - это не очень хорошая идея. Они уменьшают безопасность, поскольку они уменьшают пространство ключей.

Но более фундаментально - одно регулярное выражение, чтобы управлять ими, не является хорошей стратегией дизайна. Ваше существующее регулярное выражение достаточно длинное и сложное, что программисту по обслуживанию придется потратить некоторое время, чтобы выяснить, что он делает, и если он изменится в будущем ... вы снова будете испытывать эту головную боль.

Итак, я собираюсь предложить альтернативу - разбейте свое регулярное выражение, примените критерии проверки отдельно и дайте сообщения, чтобы сказать, почему это не удалось. Нечто подобное (реализовано на любом языке вы используете):

#!/usr/bin/env perl 
use strict; 
use warnings; 

while (<DATA>) { 
    chomp; 
    my $fail = 0; 
    print "Testing: \"$_\"\n"; 

    if (not m/.{8}/) { 
     print "Rejected because less than 8 chars\n"; 
     $fail++; 
    } 
    if (not m/[A-Z]/) { 
     print "Rejected - needs at least one upper case character\n"; 
     $fail++; 
    } 
    if (not m/\d/) { 
     print "Rejected - needs at least one digit\n"; 
     $fail++; 
    } 
    if (my @matches = m/([.,:;\'[email protected]#$%^&*_+=|(){}[?\-\]\/\\])/g) { 
     if (@matches != 1) { 
       print "Rejected - exactly one special character, not more\n"; 
       $fail++; 
     } 
    } 
    else { 
     print "Rejected - needs a special character\n"; 
     $fail++; 
    } 
    if (m/[\<\>\`]/) { 
     print "Rejected - \"<>`\" not permited\n"; 
     $fail++; 
    } 
    if (not $fail) { 
     print "$_ is OK\n"; 
    } 
} 

__DATA__ 
Fish1234! 
!!moooMoo33 
helloMum 

Это дает:

Testing: "Fish1234!" 
Fish1234! is OK 
Testing: "!!moooMoo33" 
Rejected - exactly one special character, not more 
Testing: "helloMum" 
Rejected - needs at least one digit 
Rejected - needs a special character 

(Хотя отмечу - Fish1234 не совсем надежный пароль, даже если! это действительно соответствует вашим правилам)

Смежные вопросы