英文 | https://betterprogramming.pub/21-best-practices-for-handling-passwords-in-web-applications-7b2d7a66378f
翻译 | 杨小二
哪个做法更聪明?是打破锁还是偷钥匙?
当然,你可以建立一个坚固的锁,但是,如果你不能保护钥匙,那就没有用了!
密码就像你系统的钥匙。因此,如果你是一个真诚的Web开发人员,那么,确保其实力是你的责任!
今天,我们一起来讨论一下有关密码的一些最佳做法。许多例子正在酝酿之中,请系好安全带!我们要准备开车出发了,老司机带你上路。
1、优先使用长密码而不是困难密码
鼓励用户选择更长的密码,而不是使其更难记住。
轻松+长>困难+短
这是因为大多数黑客攻击不是由试图猜测密码的人完成的,通常是由运行循环的计算机完成的。
机器不在乎难度。因此,请使用更长的密码!
2、永远不要通过电子邮件发送普通密码
不幸的是,这是开发人员中非常普遍的错误。以纯文本形式发送密码比你想象的要普遍得多。
近40%的人至少每周一次忘记密码。
因此,他们要做的是重设密码并在电子邮件中找回普通密码。
任何电子邮件都通过各种服务器发送。如果其中之一受到威胁,那么你就有麻烦了!所以永远不要这样做!
备选择方案:
文字讯息
一次密码
加密电子邮件服务
密码管理员
3、使用HTTPS进行身份验证相关页面
这是显而易见的。尽早安装有效的SSL证书!如果你有任何限制,请至少对身份验证页面执行此操作。
这不仅对安全性很重要。这对于在用户之间建立信任也很重要,并且有助于SEO。
HTTPS通过加密提供隐私。详细内容不在本文的讨论范围之内,但如果你有兴趣,你可以点击打开以下的网址资源进行学习。
资源:https://howhttps.works/
4、防止字典密码
词典密码是最常用密码的列表。密码破解者发现密码更容易破解。他们通常首先经历这些。
这是100000个最常用密码文件的列表-以此作为参考并对其进行检查。
1000万个字典密码列表地址:https://raw.githubusercontent.com/danielmiessler/SecLists/master/Passwords/Common-Credentials/10-million-password-list-top-1000000.txt
5、防止顺序密码
人们使用一些常见的序列作为密码很容易预测。
不好的例子:
qwertyuiop -> top row of keyboard
asdfghjkl -> middle row of keyboard
zxcvbnm -> bottom row of keyboard
123456 -> numeric digits in sequence
这些对于用户的手指来说比较容易,但是对安全性却不利。防止用户提供这些内容。
6、防止重复输入密码
同样,重复的密码在用户中非常普遍。它们通常很容易记住,因此很容易猜到。
不好的例子:
aaaaa1111
bbbbb22222
在前端检测到这些,并劝阻人们不要使用它们。
7、不要在数据库中存储普通密码
这意味着有权访问数据库的任何人都可以轻易地破坏所有用户帐户。
切勿将密码直接存储在数据库中。
实现某种加密。不难,为什么不呢?
8、使用哈希函数而不是加密函数
谈到加密...不使用加密功能,如SHA1,SHA2,MD5等等,这些都是设计来处理大型数据集的通用Hash函数。
始终使用bcrypt。随着bcrypt可以确定散列函数将有多贵定。下面的代码显示了它的简单程度!
由于密码不是一个很大的数据集,因此非常适合此用例。
资源:https ://codahale.com/how-to-safely-store-a-password/
9、惩罚用户
为登录不成功时,可以尝试引入一种惩罚系统。如果某人在尝试了10或者15次后仍无法登录,可以惩罚他们大约一小时后再登录。
10、考虑实现第二个用户名
在大多数网站(如Facebook)上的userName,如果你传到其个人资料,便可以从URL轻松了解用户的身份,它可以使破解更容易。
如果你确实关心安全性,则应考虑userName为用户实施第二个安全性。每个人都有不同的目的。
已知的用户名:
识别一个人
搜索资料
网上身份
未知的用户名:
这将仅用于身份验证。
只有用户会知道。
11、适当的UI设计
尽管可以在后端检查强密码,但是,你应该考虑实现某种前端验证。
禁用提交按钮直到输入有效密码为止。以下是检查密码强度的示例。
let strongPassword = new RegExp('(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[^A-Za-z0-9])(?=.{8,})')
let mediumPassword = new RegExp('((?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[^A-Za-z0-9])(?=.{6,}))|((?=.*[a-z])(?=.*[A-Z])(?=.*[^A-Za-z0-9])(?=.{8,}))')
const checkPasswordStrength = (inputPassword) => {
if(strongPassword.test(inputPassword)){
console.log('Password is strong!')
}else if(mediumPassword.test(inputPassword)){
console.log('Password strength is medium!')
}else{
console.log('Password is weak!')
}
}
const inputPassword = 'Some Password Given By User'
checkPasswordStrength(inputPassword)
资源: 带有JavaScript的密码强度检查器:https://www.p.io/engineering-education/password-strength-checker-javascript/
12、引入延迟
每次登录失败后,将延迟五秒钟,你的用户将不会感觉到它,但是攻击者会感到痛苦。
如果攻击者试图猜测用户的密码,他们将失败很多次。这将使攻击的数量级更加困难,因此不太可能在合理的时间内成功。
资源:这是一个信息性的线程:https://security.stackexchange.com/questions/94432/should-i-implement-incorrect-password-delay-in-a-website-or-a-webservice
13、劝阻替代
有人认为使用C0mpl3x而不是Complex作为密码更安全。但猜猜怎么了?其他人也知道这一点!
因此,不鼓励你的用户使用这种类型的密码,破解者无论如何都会替换掉这些替代品,因此他们只会使密码变得复杂而没有任何功能。
14、两方面身份验证
这与密码不直接相关,但与安全性相关。考虑为你的Web应用程序实施两因素身份验证。
15、密码短语更好
有两种类型的人:一种是那些相信复杂词组密码会更好,另一种是那些相信长密码短语会更好。
嗯,根据FBI的说法,较长的密码短语更适合作为密码,因为它们很难破解。
这是一个比较:
资源: https : //www.zdnet.com/article/fbi-recommends-passphrases-over-password-complexity/
16、分层
添加多层安全保护-不仅依赖于前端验证或后端验证。尝试采用多个安全级别,以便存在多个故障点。
你永远都不知道可能出什么毛病!
17、几次不正确的尝试后锁定帐户
这是相当明显的,跟踪用户是否尝试登录帐户并反复输入错误。
阻止或锁定这些帐户并运行其他验证。但是,这应取决于你的用例。
18、保持挑战性问题不可预测
如果帐户被锁定,则某些系统会使用质询问题添加第二层。
具体那些问题不可预测!例如,“你妈妈叫什么名字?” 这不是一个很好的问题,可以在用户的社交媒体页面上找到它!
好问题的答案应该是这样的。
即使几年后,也相当容易记住。
包含成千上万个可能的答案,因此不容易猜到。
这不是社交媒体上经常发现的话题。
有一个永不改变的答案(你喜欢的颜色或梦想中的汽车可能会随着时间而改变)。
示例:你的童年英雄是谁?
资源:很好的挑战性问题
19、避免密码轮换
这是一个有争议的。据说,你应该强迫用户在90天后修改一次其密码-认为这是破解密码所花费的时间。
用户中有一些不良的行为,因为他们通常希望避免频繁更改密码,因此到处都使用相同的密码!
20、鼓励用户在密码中使用空格
密码中的空格是一件好事。不幸的是,许多用户没有利用这一点。
鼓励他们使用空格-它会自动创建更安全且易于记住的密码!
21、经验法则
如果你走得这么远并且感到无聊,并且不想记住所有这些要点,那么,让我为你简化一下。只要记住一件事!使用长密码,你应该可以记得住了。
总结
大多数的时候!你已经做到了!这些准则可能并不适合所有用例,但我希望你学到了一两个你认为有用的做法!
祝你有美好的一天,我的朋友!
感谢你的阅读。
学习更多技能
请点击下方公众号