密码验证器没有特殊字符

时间:2013-09-04 18:45:57

标签: c++ regex

我是RegEx的新手,已经做了很多搜索,但没有找到具体的内容。

我正在编写一个验证密码字符串的正则表达式。 可接受的字符串必须至少有4种字符类型中的3种:数字,小写,大写,特殊字符[< + $ *]],但不得包含另一组特殊字符(|; {})。

我了解了包含(即如果它是正确的方法)。

看起来像这样:

^((a-z | A-Z |\d)(a-z|A-Z|[<+$*])(a-z|[<+$*]|\d)(A-Z|[<+$*]|\d)).*$

如何确保用户不输入特殊字符(|; {}) 这是我尝试使用排除字符串:

^(?:(?![|;{}]).)*$

我尝试了一些技巧,将两者合并在一个regEx中,但无法让它工作。

关于如何做到这一点的任何输入?

4 个答案:

答案 0 :(得分:9)

不要试图在一个正则表达式中完成所有操作。进行两次不同的检查。

假设你在Perl工作(因为你没有指定语言):

$valid_pw =
    ( $pw =~ /^((a-z | A-Z |\d)(a-z|A-Z|[<+$*])(a-z|[<+$*]|\d)(A-Z|[<+$*]|\d)).*$/ ) &&
    ( $pw !~ /\|;{}/ );

您说“如果PW符合所有包含规则,并且PW与任何排除的字符都不匹配,则密码有效。”

看看有多清楚比@Jerry的回应更清楚:

^(?![^a-zA-Z]*$|[^a-z0-9]*$|[^a-z<+$*]*$|[^A-Z0-9]*$|[^A-Z<+$*]*$|[^0-9<+$*]*$|.*[|;{}]).*$

我不怀疑Jerry的版本是否有效,但你想保留哪一个?

事实上,你可以进一步分解它并且非常清楚:

my $cases_matched = 0;
$cases_matched++ if ( $pw =~ /\d/ );       # digits
$cases_matched++ if ( $pw =~ /[a-z]/ );    # lowercase
$cases_matched++ if ( $pw =~ /[A-Z]/ );    # uppercase
$cases_matched++ if ( $pw =~ /<\+\$\*/ );  # special characters

my $is_valid = ($cases_matched >= 3) && ($pw !~ /\|;{}/); # At least 3, and none forbidden.

当然,这需要6行而不是1行,但是在你回去并且必须添加新规则或者弄清楚代码的作用的一年中,你会很高兴你这样写。< / p>

仅仅因为你可以在一个正则表达式中执行它并不意味着你应该

答案 1 :(得分:2)

您当前的正则表达式不适用于强制实施4个要求中的至少3个。使用正则表达式变得相当复杂,但在我看来,最好的方法是使用包含所有失败案例的负向前瞻,这样如果满足任何负面情况,整个匹配将失败。在这种情况下,“至少3个4”的要求也可以描述为“如果找不到任何2个组则失败”。这也使得添加最终要求变得非常容易,以确保找不到[|;{}]中的字符:

^               # beginning of string anchor
(?!             # fail if
   [^a-zA-Z]*$     # no [a-z] or [A-Z] anywhere
     |             # OR
   [^a-z0-9]*$     # no [a-z] or [0-9] anywhere
     |             # OR
   [^a-z<+$*]*$    # no [a-z] or [<+$*] anywhere
     |             # OR
   [^A-Z0-9]*$     # no [A-Z] or [0-9] anywhere
     |             # OR
   [^A-Z<+$*]*$    # no [A-Z] or [<+$*] anywhere
     |             # OR
   [^0-9<+$*]*$    # no [0-9] or [<+$*] anywhere
     |             # OR
   .*[|;{}]        # a character from [|;{}] exists
)
.*$             # made it past the negative cases, match the entire string

这是一行:

^(?![^a-zA-Z]*$|[^a-z0-9]*$|[^a-z<+$*]*$|[^A-Z0-9]*$|[^A-Z<+$*]*$|[^0-9<+$*]*$|.*[|;{}]).*$

示例:http://rubular.com/r/4YV6Aj0vqh

答案 2 :(得分:1)

这只是为了接受你提到的字符:

^(?:(?=.*[0-9])(?=.*[a-z])(?=.*[<+$*)])|(?=.*[a-z])(?=.*[<+$*)])(?=.*[A-Z])|(?=.*[0-9])(?=.*[A-Z])(?=.*[<+$*)])|(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]))[0-9A-Za-z<+$*)]+$

对于您提及的所有字符,以及除<{1}}之外的任何特殊字符。

|;{}

(一个不同之处在于第一个正则表达式不接受特殊字符^(?:(?=.*[0-9])(?=.*[a-z])(?=.*[<+$*)])|(?=.*[a-z])(?=.*[<+$*)])(?=.*[A-Z])|(?=.*[0-9])(?=.*[A-Z])(?=.*[<+$*)])|(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]))(?!.*[|;{}].*$).+$ ,但第二个正则表达式确实存在。)

我还使用了@,因为密码在逻辑上不能是0宽度。

但是,它比F.J的正则表达式更长,更长,哦。那是因为我正在使用积极的前瞻,这需要更多的检查。

答案 3 :(得分:-1)

&#34;我还没有测试过这个。我唯一不确定的可能是最后的4个最后3个检查。这使用4个捕获作为标志。这可能与其他人(可能更快)略有不同。&#34;

编辑 - 经过测试并通过。 在我看来,捕获标志是非常有用的。在这种情况下,没有前瞻,因为在这里,只检查捕获状态。而且没有回溯。它只是从头到尾检查每个字符一次。这可能是最快的方式。

 # ^(?:(?!\1)\d()|(?!\2)[a-z]()|(?!\3)[A-Z]()|(?!\4)[<+$*)]()|[^|;{}])+$(?:\1\2\3|\1\2\4|\1\3\4|\2\3\4)

 ^ 
 (?:
      (?! \1 )
      \d 
      ( )                # (1)
   |  (?! \2 )
      [a-z] 
      ( )                # (2)
   |  (?! \3 )
      [A-Z] 
      ( )                # (3)
   |  (?! \4 )
      [<+$*)] 
      ( )                # (4)
   |  [^|;{}] 
 )+
 $ 
 (?:
      \1 \2 \3
   |  \1 \2 \4
   |  \1 \3 \4
   |  \2 \3 \4 
 )