密码的正则表达式。限制特殊字符

密码的正则表达式。限制特殊字符

我正在尝试在 AWS 云形成模板中输入一些密码条目。并将密码限制为字母数字字符和特殊字符的子集。我尝试了以下方法:

"^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#@$?]).{8,}$"

这表明应该至少有一个小写和大写字母以及一个数字。另外,将特殊字符集限制为[#@$?]

我观察到,任何特殊字符(如果是最后一个字符)都是允许的。在其他任何地方都按预期被禁止

因此,Hello*E1不允许但HelloE1*允许。

如何禁止所有特殊字符,无论[#@$?]它们出现在何处?

另外,如何禁止整个特殊字符集?"^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{8,}$没有帮助。这允许所有特殊字符。

任何帮助表示赞赏。

答案1

正则表达式:

^(?=[a-zA-Z0-9#@$?]{8,}$)(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[0-9]).*

解释:

在您提供的正则表达式中,前瞻用于确保您的字符串满足某些特定条件,但它们并不是阻止不需要的字符串的真正过滤器。您指定了以下条件:

  • (?=.*?[A-Z]):至少匹配一个大写字母。
  • (?=.*?[a-z]):至少匹配一个小写字母。
  • (?=.*?[0-9]):至少匹配一个数字。
  • (?=.*?[#@$?]):至少匹配以下字符之一:#@$?
  • .{8,}:匹配任意字符至少8次。

但至少有两个缺陷:

  • (?=.*?[#@$?])部分是不必要的,因为这些特殊字符是可选的,而不是强制的[1]。

  • 正如我之前所说,您没有指定真正的过滤器,因此由于该.{8,}部分,您的正则表达式将接受任何字符串,只要它满足先行建立的条件,即使它具有不需要的特殊字符[1]。

因此,要解决这些缺陷,有必要:

  • 删除该(?=.*?[#@$?])部分。

  • 添加一个新的前瞻,充当上面提到的过滤器。

要构建此过滤器,您应该考虑“我想要允许哪些字符?”而不是“我想禁止哪些字符?”,因为在这种特定情况下这是更容易处理的情况。如果您说您只想a-zA-Z0-9#@$?成为允许的字符,那么前瞻应该如下所示:

(?=[a-zA-Z0-9#@$?])

但是,嘿,在这一步中,您甚至可以设置最小长度并告诉前瞻从哪里开始和在哪里停止(在本例中是字符串的开头和结尾):

(?=[a-zA-Z0-9#@$?]{8,}$)

^在这里省略了,因为它已经处于一切的开始,所以没有必要是多余的。现在我们只需将所有前瞻集合在一起并使用以下命令.*来匹配有效密码.{8,}

^(?=[a-zA-Z0-9#@$?]{8,}$)(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[0-9]).*

笔记:

  1. 虽然,在您提供的正则表达式和示例中,我真的不知道为什么:1)#@$?没有被视为强制性的; 2) 不需要的字符只允许出现在字符串的末尾,而不能出现在其他地方。也许这与AWS使用的正则表达式引擎有关,因为当我自己测试它时,一切都按预期工作。

答案2

我们希望针对每个所需的字符类型以及长度要求,在字符串开头锚定一个前瞻。然后简单地.*把它全部吞掉:

^(?=[0-9a-zA-Z#@\$\?]{8,}$)(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z])(?=[^0-9]*[0-9]).*

解释:

首先,我决定在匹配所需的 char 类型(例如一个大写)时避免使用惰性量词,原因如下:

  • 它们是昂贵的。
  • 不同的正则表达式引擎有不同的表示惰性的方式。 (有一对夫妇根本不支持。)
  • 它们不像替代方案那么常见/熟悉。

因此,为了提高效率、可读性和“可移植性”,我使用了该^[^x]*[x]结构。

现在把剩下的分解...

^: 一切都从头开始

(?=[0-9a-zA-Z#@\$\?]{8,}$):在字符串开头和结尾之间使用 8 个或更多允许的字符进行前瞻。

接下来的三个使用相同的模式:匹配零个或多个字符的前瞻不是匹配所需的字符,然后匹配所需的字符。这些都锚定在开头,因此效果是允许在字符串中的任何位置匹配所需的字符:

(?=[^a-z]*[a-z]): 至少一个小写字母。

(?=[^A-Z]*[A-Z]): 至少一个大写字母。

(?=[^0-9]*[0-9]) :至少一位数字。

.*:上面的所有内容都是向前看的,不会消耗任何东西,所以在这里消耗掉所有东西。第一个前瞻确保整个字符串是有效的字符,因此这是安全的。

我没有声称这是优化的(除了避免惰性量词)。这只是更容易理解的形式之一。


注意:您观察到的问题的原因#@$?是由于前瞻未锚定到字符串末尾。任何字符将在这四个字符之一之后匹配(不一定只是在最后一个位置)。当然,您不能只是添加,$因为这样会排除有效字符。这就是为什么我在同一个前瞻中包含所有有效字符。

答案3

你的正则表达式没有禁止任何字符,它只是需要每个类都有一个实例。要限制允许的字符,请更改您的.(这意味着任何字符)到允许的字符集:

^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#@$?])[a-zA-Z0-9#@$?]{8,}$

请注意,如果这意味着是一个perl字符串,则需要转义$s 和@s 或使用强引号('...'q{...})。您还需要确保正则表达式在 ASCII 模式下工作(a-z仅匹配英文字母,并.匹配任何字节)。

(?=.*?[#@$?])如果不这样做,请删除要求至少其中一个符号。

相关内容