regex - 引用 - 密码验证

标签 regex validation authentication passwords

很多时候,问题(尤其是那些标记为 的问题)询问验证密码的方法。似乎用户通常会寻求密码验证方法,包括确保密码包含特定字符、匹配特定模式和/或遵守最少字符数。这篇文章旨在帮助用户找到合适的密码验证方法,而不会大大降低安全性。

所以问题是: 应该如何正确地 验证密码?

最佳答案

Dilbert comic strip for Mordac, the preventer of information services
为什么密码验证规则不好?
我们自己的 Jeff Atwood(Coding Horror 的博主和 Stack Overflow 和 Stack Exchange 的联合创始人)在 2017 年 3 月写了一篇关于密码规​​则的博客,标题为 Password Rules are Bullshit 。如果你还没有读过这篇文章,我会敦促你这样做,因为它极大地反射(reflect)了这篇文章的意图。
如果您从未听说过 NIST (National Institute of Standards and Technology) ,那么您可能没有为您的项目使用正确的网络安全方法。在这种情况下,请查看他们的 Digital Identity Guidelines 。您还应该 及时了解有关网络安全最佳实践的 NIST Special Publication 800-63B (Revision 3) 提到了以下关于密码规​​则的内容:

Verifiers SHOULD NOT impose other composition rules (e.g. requiring mixtures of different character types or prohibiting consecutively repeated characters) for memorized secrets.


甚至 Mozilla 的 Form data validation 文档也对密码规则 (page archive here) 开玩笑:

"Your password needs to be between 8 and 30 characters long, and contain one uppercase letter, one symbol, and a number" (seriously?)


如果对密码强加组合规则会发生什么?您正在限制潜在密码的数量并删除与您的规则不匹配的密码排列。这使黑客可以确保他们的攻击也是如此! “是的,但有数万亿(1,000,000,000,000,000 或 1x1015)个密码排列”:25-GPU cluster cracks every standard Windows password in <6 hours(958 = 6,634,204,312,890,66x 密码)~105.5
xkcd
This StackExchange Security post 扩展了上面的 XKCD 漫画。
如何验证密码?
1. 不要创建自己的身份验证

Stop requiring passwords altogether, and let people log in with Google, Facebook, Twitter, Yahoo, or any other valid form of Internet driver's license that you're comfortable with. The best password is one you don't have to store.


资料来源:Your Password is Too Damn Short,作者是杰夫·阿特伍德。
2. 创建自己的身份验证
如果您确实必须创建自己的身份验证方法,请至少遵循经过验证的网络安全方法。以下两个部分(2.1 和 2.2)取自 current NIST publication 部分 5.1.1.2 Memorized Secret Verifiers
2.1.遵循经过验证的网络安全方法
NIST 声明你 应该 :
  • 要求订阅者选择的内存 key 长度至少为 8 个字符。
  • Jeff Atwood 建议普通用户的密码至少为 10 个字符,具有更高权限的用户(即管理员和版主)至少为 15 个字符。

  • 允许订阅者选择的内存密码长度不超过 64 个字符。
  • 理想情况下,您甚至不应该对此设置上限。

  • 允许所有打印 ASCII(包括空格字符)和 Unicode。
  • 出于长度要求的目的,每个 Unicode 代码点均应计为单个字符。

  • 将预期 secret 与包含已知常用、预期或已泄露的值的列表进行比较。例如:
  • 从以前的破坏语料库中获得的密码。
  • 字典词。
  • 重复或连续的字符(例如 aaaaaa1234abcd )
  • 上下文相关词,如服务名称、用户名及其派生词。

  • 为订户提供指导,例如密码强度计。
  • 实现速率限制机制,有效地限制可以在订阅者帐户上进行的失败身份验证尝试的次数(参见 Rate Limiting (Throttling) )。
  • 如果有证据表明身份验证器受到威胁,则强制更改。
  • 允许申请者在输入内存的 secret 时使用粘贴功能(便于使用密码管理器,这通常会增加用户选择更强内存的 secret 的可能性)。

  • 2.2.请勿使用本节中的任何方法!
    同一出版物还指出,您 不应 :
  • 截断 secret 。
  • 允许订阅者存储未经身份验证的 claim 人可以访问的提示。
  • 在选择记住的 secret 时,提示订阅者使用特定类型的信息(例如“你的第一只宠物的名字是什么?”)。
  • 对内存的 secret 强加其他组合规则(例如,要求混合不同的字符类型或禁止连续重复的字符)。
  • 要求任意(例如定期)更改内存的 secret 。

  • 有大量的网站解释了如何创建“正确的”密码验证表单:其中大部分已经过时,不应使用。
    3. 使用密码熵
    在您继续阅读本节之前,请注意 本节的目的不是为您提供部署您自己的安全方案 0x2518192111341142 所需的工具,而是为您提供有关当前安全方法如何验证密码的信息。如果您正在考虑创建自己的安全方案,您应该认真思考三次并阅读 StackExchange 安全社区中的 this article
    3.1.密码熵概述
    在最基本的层面上,可以使用以下公式计算密码熵:
    E = log2(R^L)
    在上面的公式中:
  • E 代表密码熵
  • R 是唯一字符池中的字符数
  • L 是密码的字符数

  • 这意味着 R^L 代表可能的密码数量;或者,就熵而言,穷尽所有可能性所需的尝试次数。
    不幸的是,这个公式没有考虑的事情是:
  • 通用密码:即 Password1 admin
  • 名称:即 John Mary
  • 常用词:即英语中 the I
  • 反转/反转字:即 drowssap(密码向后)
  • 字母替换(又名 leet):即 P@$$w0rd

  • 为这些额外的考虑添加逻辑是一个很大的挑战。有关可以添加到项目中的现有包,请参见 3.2。
    3.2.现有的密码熵项目
    在撰写本文时,用于估计密码强度的最著名的现有库是 zxcvbn by Dropbox(GitHub 上的一个开源项目)。它被改编为支持

    以错误的方式做事
    然而,我理解每个人都有不同的要求,有时人们想以错误的方式做事。对于那些符合此标准的人(或者没有选择并已将本节以上的所有内容以及更多内容提交给您的经理,但他们拒绝更新他们的方法)至少允许使用 Unicode 字符。当您将密码字符限制为一组特定的字符时(即确保存在小写 ASCII 字符 a-z 或指定用户可以或不能输入的字符 !@#$%^&*() ),您只是在自找麻烦!
    永远不要相信客户端验证 ,因为它很容易被禁用。这意味着对于那些尝试使用 STOP 验证密码的人来说。有关更多信息,请参阅 JavaScript: client-side vs. server-side validation
    以下正则表达式模式不适用于所有编程语言,但适用于许多主要编程语言 ( 0x25181221334115432104121334115432104)。请注意,以下正则表达式可能不适用于您的语言(甚至语言版本),您可能需要使用替代方案(即 :参见 )。一些编程语言甚至有更好的方法来检查这类事情(即使用 表示 Python regex matching Unicode properties ),而不是重新发明轮子。如果使用 Password Validation Plugin 中讨论的 Unicode 类的其他一些转换工具,则使用 以下是有效的。
    如果您需要防止输入控制字符,您可以使用模式 [^\P{C}\s] 在发生正则表达式匹配时提示用户。这将只匹配不是空白字符的控制字符 - 即水平制表符、换行符、垂直制表符。
    以下正则表达式确保 8 个字符以上的密码中至少存在一个小写、大写、数字和符号:
    ^(?=\P{Ll}*\p{Ll})(?=\P{Lu}*\p{Lu})(?=\P{N}*\p{N})(?=[\p{L}\p{N}]*[^\p{L}\p{N}])[\s\S]{8,}$
    
  • ^ 断言行首的位置。
  • (?=\P{Ll}*\p{Ll}) 确保至少存在一个小写字母(在任何脚本中)。
  • (?=\P{Lu}*\p{Lu}) 确保至少存在一个大写字母(在任何脚本中)。
  • (?=\P{N}*\p{N}) 确保至少存在一个数字字符(在任何脚本中)。
  • (?=[\p{L}\p{N}]*[^\p{L}\p{N}]) 确保至少存在一个不是字母或数字的任何字符(在任何脚本中)。
  • [\s\S]{8,} 匹配任意字符8次或更多次。
  • $ 断言行尾的位置。

  • 请自行决定使用上述正则表达式。你被警告了!

    关于regex - 引用 - 密码验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48345922/

    相关文章:

    security - 使用 IP 地址的 JWT 安全性

    azure - 如果我们不在应用程序设置中指定密码,Azure Linux 应用服务上的 docker 是否可以使用 ACR 进行身份验证?

    java - 带有 -,::, ( 和 ) 的正则表达式

    java - 如何在 xml 标记之间提取多语言字符串

    node.js - 如何在 Express.js 中设置身份验证中间件

    javascript - 比较开始时间和结束时间

    javascript - 如何在html中检索输入类型 'number'中的任何插入字符串

    regex - Vim 高亮正则表达式

    javascript - JS .replace(海峡, 海峡) : how to get a variable in parameter 1 yet work globally?

    c - 恶意文件上传