【问题标题】:Regex to include latin characters正则表达式包含拉丁字符
【发布时间】:2018-06-21 04:37:29
【问题描述】:

我有一个正则表达式来确保密码包含大小写字符,并且仅限于几个符号:

^(?:(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z])(?=.*[$@$!%*?&,;.:-_])[A-Za-z\d$@$!%*?&,;.:-_]+)?$

注意:它允许空密码。我正在检查另一种方式。

但它不允许使用诸如ç、á、õ等拉丁字符。

如何添加这种类型的字符?

更新

我正在尝试创建与 Microsoft 选项同步的密码验证正则表达式,例如:

RequireDigit (Default = true) 
  Requires a number between 0-9 in the password.

RequireNonAlphanumeric (Default = true)     
  Requires a non-alphanumeric character in the password.

RequireUppercase (Default = true)   
  Requires an upper case character in the password.

RequireLowercase (Default = true)   
  Requires a lower case character in the password.

RequiredUniqueChars (Default = 1)   
  Requires the number of distinct characters in the password

微软文档:https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity-configuration?tabs=aspnetcore2x

所以我希望每个规则都有一个带有块的正则表达式,这样我就可以通过添加或删除规则并进行任何组合来更改它。

这有意义吗?

【问题讨论】:

  • 不要限制符号。此外,使用字符类\p{Ll} 是任何脚本中的任何小写字母。 Microsoft's documentation 涵盖了这个
  • 您为密码设置的规则越多,攻击的针对性就越强。不要过滤任何字符,反正都是加盐和散列
  • 请不要让我们遵循你奇怪的规则。最小字符长度应该足够了。
  • 它允许使用空密码,因为您将整个内容封装在一个捕获组中(为什么?)并在其后加上?,从而使整个模式成为可选的。即使忽略这一点,内部模式也允许长度在 3 到无限个字符之间的字符串。 3 是相当低的,我相信你也会想要一个上限,对吧?
  • 如果出于某种奇怪的原因,您必须验证密码,至少允许任何脚本中的任何字符工作,并且不要将字符限制为特定的集合:@ 987654327@

标签: c# regex


【解决方案1】:

概述

限制密码通常是不好的做法,所以如果这是故意的,请不要使用以下正则表达式。无论如何,我知道有些人喜欢至少确保某些字符集存在(大写、小写、数字、符号等),并且在需要这样的事情时存在特殊情况。下面的正则表达式确保至少一个小写字母、大写字母、数字和符号(在任何语言/脚本中)存在于至少 8 个字符的字符串中。

正如问题下方的 cmets 所建议的那样,将密码限制为特定的字符集或特定格式只是​​自找麻烦。正如@maccettura 所建议的那样,攻击者可以过滤字典攻击并消除大量与您的密码格式不匹配的字典项。写入,例如[A-Za-z\d$@$!%*?&,;.:-_],攻击者可以简单地删除任何包含列表中字符以外的字符的密码。该列表也仅包含 75 个字符。 75 个字符的排列有多少种?对于长度为 8 个字符的密码,680,240,886,192,000 排列(如果我们删除与下面的正则表达式不匹配的密码,则更少)。你的 CPU 需要多长时间才能破解密码?

请参阅以下有关密码的 StackExchange 帖子:

其他文章:

代码

See regex in use here

^(?=\P{Ll}*\p{Ll})(?=\P{Lu}*\p{Lu})(?=\P{N}*\p{N})(?=.*[^\p{‌​L}\p{N}\p{C}]).{8,}$

说明

\p{x}表示x指定的Unicode通用类别或命名块

  • ^ 在行首断言位置
  • (?=\P{Ll}*\p{Ll}) 确保任何脚本中至少存在一个小写字母
  • (?=\P{Lu}*\p{Lu}) 确保任何脚本中至少存在一个大写字母
  • (?=\P{N}*\p{N}) 确保任何脚本中至少存在一个数字字符
  • (?=.*[^\p{‌​L}\p{N}\p{C}]) 确保存在除字母、数字或控制字符以外的任何字符
  • .{8,} 确保密码长度至少为 8 个字符(并且不受上限限制)
  • $在行尾断言位置

【讨论】:

  • 请问在你的前瞻中使用否定有什么好处?例如使用(?=\P{Ll}*\p{Ll}) 与使用(?=.*\p{Ll}) 相比有什么优势
  • @JackPRead 它让它稍微快一点。看看我原来的正则表达式 here 上的步数,以及当我替换单个否定集 here 时。步数增加 1。或者,也可以使用.*?(无需额外的步骤),但在没有找到匹配项的情况下,.*? 将比\P{Ll} 执行更多的步骤(如here)来完成如here 所见,因为它会回溯。
  • 经过深思熟虑,这完全有道理。谢谢。实际上,如果您使通配符上的量词变得懒惰,您可以获得相同的结果。例如here。我认为如果搜索一个大字符串,你的方式可能仍然更好。
  • @JackPRead 我更新了我之前的评论以包含惰性量词。虽然它确实表明它可能是等效的,但当模式无法匹配字符串时它实际上会更慢(27 步,而不是在这种情况下为 4 步)。这是由于回溯。
  • 一些琐事.. 这可能/可能不是可取的,我不知道。在匹配 [^\p{L}\p{N}\p{C}] 的大约 9763 个字符中,也包括这些 \p{Block=Combining_Diacritical_Marks} U+300 - U+36f
猜你喜欢
  • 2016-05-13
  • 2018-10-13
  • 2015-07-09
  • 1970-01-01
  • 2013-01-27
  • 2022-01-21
  • 2014-12-20
  • 2015-02-26
  • 2011-06-27
相关资源
最近更新 更多