很多时候,问题(尤其是那些标记为 regex 的问题)询问验证密码的方法。似乎用户通常会寻求密码验证方法,包括确保密码包含特定字符、匹配特定模式和/或遵守最少字符数。这篇文章旨在帮助用户找到合适的密码验证方法,而不会大大降低安全性。
所以问题是: 应该如何正确地 验证密码?
最佳答案
为什么密码验证规则不好?
我们自己的 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
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 声明你 应该 :
aaaaaa
、 1234abcd
) 2.2.请勿使用本节中的任何方法!
同一出版物还指出,您 不应 :
有大量的网站解释了如何创建“正确的”密码验证表单:其中大部分已经过时,不应使用。
3. 使用密码熵
在您继续阅读本节之前,请注意 本节的目的不是为您提供部署您自己的安全方案 0x2518192111341142 所需的工具,而是为您提供有关当前安全方法如何验证密码的信息。如果您正在考虑创建自己的安全方案,您应该认真思考三次并阅读 StackExchange 安全社区中的 this article。
3.1.密码熵概述
在最基本的层面上,可以使用以下公式计算密码熵:
在上面的公式中:
这意味着 代表可能的密码数量;或者,就熵而言,穷尽所有可能性所需的尝试次数。
不幸的是,这个公式没有考虑的事情是:
Password1
admin
John
Mary
the
I
drowssap
(密码向后) P@$$w0rd
为这些额外的考虑添加逻辑是一个很大的挑战。有关可以添加到项目中的现有包,请参见 3.2。
3.2.现有的密码熵项目
在撰写本文时,用于估计密码强度的最著名的现有库是 zxcvbn by Dropbox(GitHub 上的一个开源项目)。它被改编为支持.net angularjs c c# c++ go java javascript objective-c ocaml php python rest ruby rust scala
以错误的方式做事
然而,我理解每个人都有不同的要求,有时人们想以错误的方式做事。对于那些符合此标准的人(或者没有选择并已将本节以上的所有内容以及更多内容提交给您的经理,但他们拒绝更新他们的方法)至少允许使用 Unicode 字符。当您将密码字符限制为一组特定的字符时(即确保存在小写 ASCII 字符
a-z
或指定用户可以或不能输入的字符 !@#$%^&*()
),您只是在自找麻烦!永远不要相信客户端验证 ,因为它很容易被禁用。这意味着对于那些尝试使用 javascript STOP 验证密码的人来说。有关更多信息,请参阅 JavaScript: client-side vs. server-side validation。
以下正则表达式模式不适用于所有编程语言,但适用于许多主要编程语言 ( java .net php 0x25181221334115432104121334115432104)。请注意,以下正则表达式可能不适用于您的语言(甚至语言版本),您可能需要使用替代方案(即 perl :参见 ruby )。一些编程语言甚至有更好的方法来检查这类事情(即使用 python 表示 Python regex matching Unicode properties ),而不是重新发明轮子。如果使用 Password Validation Plugin 或 mysql 中讨论的 Unicode 类的其他一些转换工具,则使用 node.js 以下是有效的。
如果您需要防止输入控制字符,您可以使用模式
[^\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/