正则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
如果提供的密码确实包含空格,则所有的检查都将完成,只有最后的检查在空间上失败。 这可以通过用\S
replace所有的点来避免:
\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式模式。