- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我对确保用户身份验证安全的最佳方法有疑问。
我遇到过一个在后端加密用户密码的网络应用程序。然而,这种加密是使用所有密码相同的 key 来完成的。此外,此 key 在后端“硬编码”。
他们(应用程序开发人员)声称这是完全安全的。不过我有疑问。我相信这种方法会导致两个问题:
对密码进行加密的原因是为了避免在未经授权的数据库访问时访问密码。但是,如果您将 key 存储在同一服务器中,他们也有可能获得 key 。
相同的密码将产生相同的加密值,因此更容易攻击系统。
我的问题如下:
我的说法正确吗?如果真的那么不安全,我应该警告他们可能的威胁吗?
使用哈希 + salt 方法有何优缺点?
谢谢!
最佳答案
我不确定您是否可能错误地将加密和散列混淆在一起。如果用户的密码被加密而不是散列,那么在发生数据泄露时,攻击者就有可能窃取所有用户密码。
在身份验证方面,您似乎需要考虑许多因素。首先,任何散列都应该在后端完成,而不是在前端完成。前端的散列仍然会让您容易受到散列攻击。
一些开发人员采用双哈希方法,在前端对密码进行哈希处理,然后在后端重新对其进行哈希处理。我认为这是不必要的,前端密码应该被HTTPS层覆盖( TLS ),但这还有待讨论。
首先,我们先澄清两个关键术语,然后再解释如何安全地存储和验证用户。
您指定用户的密码被加密,而不是被散列。加密函数的作用是以一对一的方式将输入(用户的密码)映射到输出(加密的密码),这意味着这是可逆的。
这意味着,如果黑客获得了加密 key (私钥),他们就可以轻松逆转整个过程。
相反,用户的密码应该在服务器端散列。为什么?因为您可以通过比较两个哈希值来检查它们是否匹配,而无需存储该值的纯文本表示形式。
您可能会再问,“为什么”?因为哈希函数是单向的,这意味着纯文本值无法反转(嗯,它们很难反转),所以我不会详细介绍。
用户的密码决不应该以纯文本形式存储在网络服务器的任何部分。相反,您应该存储用户的哈希值。当用户尝试登录时,您通过 HTTPS/TLS 安全地接收他们的纯文本密码,对其进行哈希处理,如果两个哈希值匹配,则对用户进行身份验证。
因此数据库表可能如下所示:
+--------------------------------------+
| ID | Username | Password Hash |
+--------------------------------------+
| 1 | foo | $2a$04$/JicM |
| 2 | bar | $2a$04$cxZWT |
+--------------------------------------+
现在让我们举一个例子,在 Alice 和我们的服务器之间。不要太从字面上理解数据。
Alice 发送使用她的凭据登录的请求,该请求首先通过我们的安全传输层:
{用户名:“foo”,密码:“bar”} -> TLS() -> ZwUlLviJjtCgc1B4DlFnK -> |服务器|
我们的服务器收到此信息,然后使用其证书 key 来解密:
ZwUlLviJjtCgc1B4DlFnK -> KEY() -> {用户名:“foo”,密码:“bar”} -> Web 应用程序
太棒了!我们的凭据已安全传递,现在怎么办?对该密码进行哈希处理并与我们在数据库中获得的内容进行比较。
BCRYPT('bar') -> $2a$04$/JicM
if ($2a$04$/JicM == user.get_password_hash) {
authenticate();
}
else {
return status_code(401);
}
我们现在已经能够对用户进行身份验证,存储不可逆的哈希值,而无需存储纯文本值。这应该已经回答了您的第一个问题和第二个问题。
关于security - 后端密码加密与散列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36892173/
我是一名优秀的程序员,十分优秀!