正则expression式Java用于密码validation

我正在创build一个用于Java应用程序的密码validation的正则expression式作为configuration参数。

正则expression式是:

^.*(?=.{8,})(?=..*[0-9])(?=.*[az])(?=.*[AZ])(?=.*[@#$%^&+=]).*$ 

密码策略是:

  • 至less8个字符

  • 包含至less一个数字

  • 至less包含一个较低的字母字符和一个较高的字母字符

  • 在一组特殊字符( @#%$^等)中至less包含一个字符。

  • 不包含空格,标签等

我错过了第5点。我不能有正则expression式检查空间,制表符,回车等。

任何人都可以帮我吗?

尝试这个:

 ^(?=.*[0-9])(?=.*[az])(?=.*[AZ])(?=.*[@#$%^&+=])(?=\S+$).{8,}$ 

说明:

 ^ # start-of-string (?=.*[0-9]) # a digit must occur at least once (?=.*[az]) # a lower case letter must occur at least once (?=.*[AZ]) # an upper case letter must occur at least once (?=.*[@#$%^&+=]) # a special character must occur at least once (?=\S+$) # no whitespace allowed in the entire string .{8,} # anything, at least eight places though $ # end-of-string 

因为每个规则都是一个独立的“模块”,所以添加,修改或删除单个规则是很容易的。

(?=.*[xyz])构造吃掉整个string( .* ),并回溯到[xyz]可以匹配的第一个匹配项。 如果find[xyz] ,则成功,否则失败。

另一种方法是使用一个不情愿的限定符: (?=.*?[xyz]) 。 对于密码检查,这几乎没有任何区别,对于更长的string,它可能是更有效的变体。

当然,最有效的变体(但是最难读取和维护,因此最容易出错)将是(?=[^xyz]*[xyz]) 。 对于这个长度的正则expression式,为此,我会不推荐这样做,因为它没有真正的好处。

使用正则expression式的简单例子

 public class passwordvalidation { public static void main(String[] args) { String passwd = "aaZZa44@"; String pattern = "(?=.*[0-9])(?=.*[az])(?=.*[AZ])(?=.*[@#$%^&+=])(?=\\S+$).{8,}"; System.out.println(passwd.matches(pattern)); } } 

说明:

  • (?=.*[0-9])数字必须至less出现一次
  • (?=.*[az])小写字母必须至less出现一次
  • (?=.*[AZ])大写字母必须至less出现一次
  • (?=.*[@#$%^&+=])一个特殊字符必须至less出现一次
  • (?=\\S+$)在整个string中不允许有空格
  • .{8,}至less8个字符

所有以前给出的答案都使用相同的(正确的)技术来为每个需求使用单独的前瞻。 但是它们包含了一些效率低下和潜在的巨大bug,具体取决于实际使用密码的后端。

我将从接受的答案开始:

 ^(?=.*[0-9])(?=.*[az])(?=.*[AZ])(?=.*[@#$%^&+=])(?=\S+$).{8,}$ 

首先,由于Java支持\A\z我更喜欢使用这些来确保整个string被validation,与Pattern.MULTILINE无关。 这不会影响性能,但可避免正则expression式回收时的错误。

 \A(?=.*[0-9])(?=.*[az])(?=.*[AZ])(?=.*[@#$%^&+=])(?=\S+$).{8,}\z 

检查密码是否包含空格并检查其最小长度可以通过一次性使用all来完成,方法是在速记\S上放置variablesquantifier {8,} ,以限制允许的字符:

 \A(?=.*[0-9])(?=.*[az])(?=.*[AZ])(?=.*[@#$%^&+=])\S{8,}\z 

如果提供的密码确实包含空格,则所有的检查都将完成,只有最后的检查在空间上失败。 这可以通过用\Sreplace所有的点来避免:

 \A(?=\S*[0-9])(?=\S*[az])(?=\S*[AZ])(?=\S*[@#$%^&+=])\S{8,}\z 

只有在你真的想要允许任何angular色的时候才能使用这个点。 否则,使用(否定的)字符类将您的正则expression式限制为仅允许那些真正允许的字符。 虽然在这种情况下几乎没有什么区别,但是在别的东西更合适的时候不使用点是非常好的习惯。 我看到太多灾难性回溯的例子,因为开发者懒得使用比点更合适的东西。

由于初始testing很有可能在密码的前半部分find适当的字符,所以懒惰的量词可以更有效率:

 \A(?=\S*?[0-9])(?=\S*?[az])(?=\S*?[AZ])(?=\S*?[@#$%^&+=])\S{8,}\z 

但是现在真正重要的问题是:没有一个答案提到这个事实,即原来的问题似乎是由ASCII认为的人写的。 但是在Java中,string是Unicode的。 密码中是否允许使用非ASCII字符? 如果是,则只允许ASCII空格,或者应排除所有Unicode空格。

默认情况下\s只匹配ASCII空格,所以它的\S匹配所有Unicode字符(不包括空格)和所有非空白ASCII字符。 如果允许Unicode字符但Unicode空格不允许,可以指定UNICODE_CHARACTER_CLASS标志使\S排除Unicode空格。 如果不允许使用Unicode字符,则可以使用[\x21-\x7E]替代\S来匹配不是空格或控制字符的所有ASCII字符。

这给我们带来了下一个潜在的问题:我们是否想要允许控制字符? 编写正确的正则expression式的第一步是准确地指定要匹配的内容以及不匹配的内容。 唯一的100%技术上正确的答案是,问题中的密码规范是不明确的,因为它没有说明是否允许某些范围的字符,如控制字符或非ASCII字符。

你不应该使用过于复杂的正则expression式(如果你能避免它们),因为它们是

  • 很难阅读(至less除了你自己以外)
  • 很难延续
  • 很难debugging

尽pipe在使用许多小正则expression式时可能会有小的性能开销,但上面的点很容易。

我会这样实现:

 bool matchesPolicy(pwd) { if (pwd.length < 8) return false; if (not pwd =~ /[0-9]/) return false; if (not pwd =~ /[az]/) return false; if (not pwd =~ /[AZ]/) return false; if (not pwd =~ /[%@$^]/) return false; if (pwd =~ /\s/) return false; return true; } 

密码要求:

  • 系统可以支持的密码长度不得less于八(8)个字符。
  • 密码必须包含至less两个这样的分组中的字符:字母,数字和特殊字符。

     ^.*(?=.{8,})(?=.*\d)(?=.*[a-zA-Z])|(?=.{8,})(?=.*\d)(?=.*[!@#$%^&])|(?=.{8,})(?=.*[a-zA-Z])(?=.*[!@#$%^&]).*$ 

我testing了它,它工作

我认为这也可以做到(作为一个更简单的模式):

 ^(?=.*\d)(?=.*[az])(?=.*[AZ])(?=.*[@#$%^&+=])[^\s]{8,}$ 

[正则expression式演示]

对于任何对每种angular色最低要求感兴趣的人,我都会build议对Tomalak公认的答案作以下扩展:

 ^(?=(.*[0-9]){%d,})(?=(.*[az]){%d,})(?=(.*[AZ]){%d,})(?=(.*[^0-9a-zA-Z]){%d,})(?=\S+$).{%d,}$ 

注意,这是一个格式化string,而不是最终的正则expression式模式。 只需将%dreplace为数字,小写字母,大写字母,非数字/字符以及整个密码(分别)的最小必需出现次数即可。 最大发生率是不太可能的(除非你想最大值为0,有效地拒绝任何这样的字符),但是也可以很容易地添加。 注意每种types的额外分组,以便最小/最大限制允许非连续匹配。 这对于我们可以集中configuration我们需要的每种字符types的系统的奇迹,然后使网站以及两个不同的移动平台获取该信息来构build基于上述格式化string的正则expression式模式。