如何将正确的前瞻性正则表达式添加到角色白名单中

时间:2011-03-04 17:57:21

标签: .net regex

我正在使用以下正则表达式验证我的密码强度。

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

批准列表中的8-12个字符,至少1个小写字母,1个大写字母,1个数字和1个特殊字符。 (我知道我不能只在前面设置{1,4}并让它正常工作,但我希望尽快解决这个问题,所以我就这样离开了。)

表达式似乎有点冗长,但我的用户可以设置自己的密码规则,这似乎是在正则表达式中创建可互换部分的最佳方式。

为此,我想补充一点,所有字符必须在集合

[A-Z]|[a-z]|[0-9]|[@\#\$%\^&\+=!\?\*]

如果该组中没有任何字符,则该行不匹配。

不幸的是,我没有找到正确的表达方式。非常感谢任何帮助。

如果与讨论相关,我正在使用.net实现。

2 个答案:

答案 0 :(得分:1)

如果找不到集合中定义的任何内容,您可以使用负面外观来使匹配失败。

首先,将所有字符分组到一个类中,并指定您希望通过在开头使用插入符来匹配此类中的任何 not

[^A-Za-z0-9@\#\$%\^&\+=!\?\*]

接下来,使用此负面字符类和负面外观更新模式:

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

此外,您通常不需要在字符类中转义元字符,因此您可以通过删除转义来进一步清理模式。这会缩短这种模式:

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

当然,如果您允许破折号,请务必将其转义或将其放在字符类的开头或结尾,以避免意外指定一系列字符。如果您的用户可以提供模式信息,这很重要,在这种情况下,您可能希望在任何用户提供的输入上使用Regex.Escape method

答案 1 :(得分:1)

我不明白为什么你这样使用正则表达式。密码不遵循模式,它们遵循一套规则。而不是尝试将其与模式匹配,而是根据一组规则进行检查:

伪代码:

function checkPassword(password, rules)
{
  for (i = 0; i < rules.length; i++)
  {
    if ( !rules[i]( password ) ) return false;
  }
  return true;
}

function hasCapital(password)
{
  return password.matches(/[A-Z]/);
}
function hasLower(password)
{
  return password.matches(/[a-z]/);
}
function hasNumber(password)
{
  return password.matches(/[0-9]/);
}
function hasSpecial(password)
{
  return password.matches(/[@\#\$%\^&\+=!\?\*]/);
}

password = getPassword();
passwordIsValid = false;
rules = [];
rules[] = hasCapital;
rules[] = hasLower;
rules[] = hasNumber;
rules[] = hasSpecial;

passwordIsValid = checkPassword( password, rules );

这种格式是模块化的,您可以指定您想要的任何规则,它会告诉您是否有任何规则被破坏。此外,您会注意到实际使用的RegEx会产生,因此可调试。

如果您使用的是RegEx,它应该简化您的代码,而不是让它更难理解。