在mysql中存储密码......使用哈希对吗?但是您如何向用户发送忘记的密码?

Posted

技术标签:

【中文标题】在mysql中存储密码......使用哈希对吗?但是您如何向用户发送忘记的密码?【英文标题】:Storing passwords in mysql... use a hash right? but how do you send the user a forgotten password? 【发布时间】:2012-10-29 21:13:24 【问题描述】:

我一直在研究将用户密码存储在 mysql 中,而普遍的答复是使用 MD5 或 SHA1 等加密算法存储它。但是如果用户 x 忘记了她的密码并希望将其发送给她怎么办?然后怎样呢?我无法向她发送 md5 哈希!这个问题在现实世界中是如何处理的。有两个数据库吗?一个比较哈希值,另一个比较忘记密码?但是有什么区别,当时连接到它的sql用户都是只读的。你是怎么做到的?谢谢!!

【问题讨论】:

请输入密码作为单向街道。即从用户到您自己,而不是相反。有几个问题和captha。还可以在冷静期之前启用几次尝试,以防止有人试图破解它。 不要使用 MD5 或 SHA1 对其进行哈希处理。它们不适用于散列密码。使用 bcrypt。如果您想让自己更轻松,请使用password_compat lib。 【参考方案1】:

从不向用户发送密码是非常标准的安全做法。相反,您提供了一个密码重置实用程序,该实用程序与他们访问其电子邮件帐户的能力和/或回答有关其个人资料的问题(例如安全问题或他们居住的邮政编码)的能力相关联。

功能概述:

    用户点击“忘记密码链接” 用户输入安全挑战信息(电子邮件地址、安全问题,如果需要) 系统发送带有自动生成链接的密码重置电子邮件(例如,在查询字符串中生成 GUID) 系统会创建一个密码重置记录,其中包含重置 GUID、它的用户以及密钥何时超时。 用户检索电子邮件,点击链接。 系统匹配 GUID,删除密码重置记录,将用户发送到密码重置页面。

【讨论】:

添加安全问题是个好主意。否则,入侵用户电子邮件帐户的人不难获得对您网站(以及用户信息)的访问权限。额外的安全层(例如安全问题)可以帮助防止这种情况发生。 我不同意安全问题 - 他们几乎添加了零安全性 如果受保护的服务比电子邮件通道的所有权更敏感,则需要辅助凭据(可能是安全问题或其他)。由于电子邮件以明文形式发送到本身经常被盗的帐户,因此许多第三方可能可以访问重置代码。对于一个点头网络论坛帐户,您不会打扰;对于像网上银行这样的东西,你就是。【参考方案2】:

最好的解决方案是向用户发送一个链接,让他们可以输入新密码而无需输入忘记的密码。

这个链接应该只能工作一次,而且应该只能工作几个小时。

不要创建新密码并通过邮件发送;用户会很想使用该密码(忽略通过不安全通道传输的事实)。

【讨论】:

不知道为什么您认为这比重新生成一个新的并在第一次使用时强制更改要好。 用户更容易记住他们自己设置的密码,如果有人拦截了重置邮件,至少你有他们的 IP 地址日志,因为他们必须到你的站点执行重置。 @pseudocoder 您不一定会记录他们的 IP 地址,即使您这样做也无济于事 @jah 在本 QA 的两个 cmets 中,您假设站点运营商没有进行安全准备,并且用户的身份完全受到威胁。在这种情况下,您是对的,没有太多可以防止帐户被盗的措施。网站运营商的工作是将这些情况边缘化,而不是消除它们。 @jah 我的意思是没有任何安全级别是绝对的,因此评论某些安全措施在某些情况下无效确实是一个有争议的问题。问题在于,考虑到您想要保护的内容的敏感性,某些安全措施是否可以为大部分场景提供保护。我相信这个线程中讨论的模型适用于大多数通用密码恢复情况;至少在传闻中,这种信念得到了目前使用它的网站的普遍支持。【参考方案3】:

您是正确的,密码不应以纯文本 (they should be hashed) 形式存储,因此无法将密码传递给忘记密码的用户。

本质上,您想要的是一种绕过正常身份验证方案的方法,您首先应该意识到这种机制是应用程序的后门。

通常会假设只有所需用户才能访问发送到在您的应用程序中注册的电子邮件地址的电子邮件。 “标准”密码重置机制正是基于此假设。这是我的看法:

    请求忘记密码页面,并要求用户在表单中输入他们注册的电子邮件地址,然后提交 接收代码检查提交的电子邮件地址是否确实已注册,如果是: 从相应的存储中删除此地址的所有现有密码重置令牌 为此地址生成并存储新的密码重置令牌 向用户发送一封电子邮件,通知他们 “某人”请求重设密码 如果他们确实希望重置,请单击链接 如果他们没有请求重置,则忽略电子邮件 响应表单提交,页面上写着“如果提交的地址已注册,则已发送重置电子邮件” 如果提交的地址不是在应用程序中注册的地址,则什么也不做,只使用一个页面回复提交,该页面显示类似于“如果提交的地址已注册然后一封重置电子邮件”已发送” - 就像地址是有效地址一样(这是为了让某人更难发现在应用程序中注册的电子邮件地址) 然后用户会收到忘记密码的电子邮件并单击其中的链接。该链接将密码重置令牌传递给应用程序。 收到密码重置令牌后,代码会检查该令牌是否存在于存储中并且尚未过期。如果这些都成立,那么您假设必须是提交令牌的注册用户,您可以允许他们设置新密码(带有密码和密码确认输入和提交按钮的简单表单,其中包含零个人信息 -甚至没有他们的名字)。 设置密码后,您可以将用户引导至登录页面,让他们正常输入凭据。

这不是一个完美的方案。这是安全性和便利性之间的权衡,毫无疑问它构成了应用程序的后门。对于低价值的应用程序,它通常就足够了。

进一步阅读:

https://www.owasp.org/index.php/Forgot_Password_Cheat_Sheet Forgot Password: what is the best method of implementing a forgot password function? Why is "Forgotten Password" bad?

【讨论】:

我只是想知道这一点。大网站是如何忘记密码的?而不是总是需要新密码? @phileaton 也许是因为他们已经决定在更适合他们的安全性和便利性之间进行权衡;也许是因为他们不知道自己在做什么。 我特别喜欢第 3 点。如果有人开发一种工具来使用生成的哈希访问网站,希望偶尔得到一个有效的哈希,这将是相当容易的。如果他们这样做了,并且他们更改了密码,那么他们最好不知道他们更改了谁的密码。如果发生这种情况,用户始终可以通过正常机制再次重置密码。 @phileaton - Google 不会向您发送您的密码。 请注意,密码应该是哈希,而不是加密,加密意味着它可以解密回到一个纯文本密码。散列是一种单向算法。

以上是关于在mysql中存储密码......使用哈希对吗?但是您如何向用户发送忘记的密码?的主要内容,如果未能解决你的问题,请参考以下文章

在 PHP 中创建安全密码哈希但检查 Access VBA

从 MYSQL 数据库检索后,PHP 中的哈希密码不是字符串

使用 dcrypt 对密码进行哈希处理后,使用 MySQL 中的 NodeJs 登录用户

用于登录密码的 PHP 盐和哈希 SHA256

哈希密码的最佳实践

带有 BCrypt 哈希的 AES 256。如何从数据库中检查用户密码? [复制]