当我继续建立越来越多的网站和网络应用程序时,我经常被要求存储用户的密码,如果/当用户有问题时,它们可以被检索(要么通过电子邮件发送一个忘记密码的链接,通过电话等),当我可以与这种做法作斗争时,我做了大量的“额外”编程,使密码重置和管理协助成为可能,而不存储他们的实际密码。

当我无法对抗它(或无法获胜)时,我总是以某种方式对密码进行编码,这样至少它不会以明文形式存储在数据库中——尽管我知道如果我的数据库被黑客攻击,罪犯不需要花费太多时间就能破解密码,所以这让我感到不舒服。

在一个完美的世界里,人们会经常更新密码,而不会在许多不同的网站上重复密码——不幸的是,我知道很多人都有相同的工作/家庭/电子邮件/银行密码,甚至在他们需要帮助的时候免费给我。如果我的数据库安全程序因为某种原因失败了,我不想成为他们财务崩溃的罪魁祸首。

从道德和伦理上讲,我觉得我有责任保护一些用户的生活,即使他们对他们的生活不那么尊重。 我确信有许多方法和论点可以用于盐散列和不同的编码选项,但当您必须存储它们时,是否存在单一的“最佳实践”?在几乎所有的情况下,我使用PHP和MySQL,如果这使任何不同的方式,我应该处理的细节。

Bounty的其他信息

我想澄清的是,我知道这不是你想要做的事情,在大多数情况下,拒绝这样做是最好的。然而,我并不是在寻求关于采用这种方法的优点的说教,我是在寻找如果你确实采用这种方法,应该采取的最佳步骤。

在下面的注释中,我指出了主要面向老年人、智障人士或非常年轻的人的网站,当他们被要求执行安全密码恢复程序时,他们会感到困惑。尽管在这些情况下,我们可能会发现这很简单,但有些用户需要额外的帮助,要么让服务技术人员帮助他们进入系统,要么通过电子邮件/直接显示给他们。

在这样的系统中,如果用户没有得到这种级别的访问帮助,来自这些人口统计数据的流失率可能会阻碍应用程序,所以请在回答时考虑到这样的设置。

谢谢大家

这是一个有趣的问题,有很多争论,我很喜欢。最后,我选择了一个答案,它既保留了密码安全性(我不必保留纯文本或可恢复的密码),又使我指定的用户群能够登录到一个系统,而不存在我在正常密码恢复中发现的主要缺陷。

像往常一样,由于不同的原因,大约有5个答案我想标记为正确,但我必须选择最好的一个——其余的都是+1。谢谢大家!

同时,感谢Stack社区中为这个问题投票和/或将其标记为最喜欢的人。我把获得100票作为一种赞美,希望这个讨论能帮助到和我有同样担忧的人。


当前回答

抱歉,但只要你有办法破解他们的密码,就不可能是安全的。痛苦地抗争,如果你输了,CYA。

其他回答

另一个你可能没有考虑到的选择是允许通过电子邮件进行操作。这有点麻烦,但我为一个客户端实现了这个功能,该客户端需要系统“外部”的用户来查看(只读)系统的某些部分。例如:

一旦用户注册,他们就拥有完全的访问权限(就像普通用户一样) 网站)。注册必须包括电子邮件。 如果需要数据或操作,而用户不需要 记住他们的密码,他们仍然可以通过 点击一个特殊的“给我发邮件以获得许可”按钮,就在常规的“提交”按钮旁边。 然后,请求以超链接发送到电子邮件,询问他们是否希望执行该操作。这类似于密码重置电子邮件链接,但它不是重置密码,而是执行一次性操作。 然后用户点击“Yes”,它确认应该显示数据,或者应该执行操作,显示数据等等。

正如你在评论中提到的,如果电子邮件被泄露,这将不起作用,但它确实解决了@joachim关于不想重置密码的评论。最终,他们将不得不使用密码重置,但他们可以在更方便的时候这样做,或者根据需要在管理员或朋友的帮助下这样做。

该解决方案的另一种方法是将操作请求发送给第三方可信管理员。这对于老年人、智障人士、非常年轻或其他困惑的用户来说效果最好。当然,这需要一个可信的管理员来支持这些人的行动。

我也有同样的问题。同样的,我总是认为有人入侵我的系统不是“如果”的问题,而是“什么时候”的问题。

所以,当我必须做一个网站,需要存储一个可恢复的机密信息,如信用卡或密码,我所做的是:

使用openssl_encrypt(字符串$data,字符串$method,字符串$password)进行加密 PHP手册。 数据参数: 敏感资料(例如用户密码) 如果需要,序列化,例如,如果信息是一个数据数组,如多个敏感信息 密码arg:使用一个只有用户知道的信息,比如: 用户牌照 社会保险号码 用户电话 用户母名 在注册时通过电子邮件和/或短信发送的随机字符串 方法参数: 选择一种密码方法,如“aes-256-cbc” 永远不要将password参数中使用的信息存储在数据库(或系统中的任何地方)

当需要检索此数据时,只需使用“openssl_decrypt()”函数并向用户询问答案。例如:“要收到你的密码,请回答这个问题:你的手机号码是多少?”

PS 1:永远不要将存储在数据库中的数据用作密码。如果您需要存储用户的手机号码,那么永远不要使用此信息来编码数据。总是使用只有用户知道的信息,或者非亲属很难知道的信息。

PS 2:信用卡信息,比如“一键购买”,我所做的就是使用登录密码。这个密码在数据库中哈希(sha1, md5等),但在登录时,我将明文密码存储在会话或非持久性(即在内存中)安全cookie中。这个简单的密码永远不会留在数据库中,实际上它总是留在内存中,在节结束时销毁。当用户点击“一键购买”按钮时,系统使用此密码。如果用户使用facebook, twitter等服务登录,那么我会在购买时再次提示密码(好吧,这不是完全的“点击”),然后使用用户曾经登录的服务的一些数据(如facebook id)。

刚刚看到这个有趣而热烈的讨论。 最让我惊讶的是,很少有人关注以下基本问题:

Q1。用户坚持访问纯文本存储的密码的实际原因是什么?为什么它这么有价值?

用户年龄大或小的信息并不能真正回答这个问题。但是,如果没有正确理解客户的关注点,如何做出业务决策呢?

为什么这很重要呢? 因为如果客户要求的真正原因是系统难以使用,那么解决具体原因可能会解决实际问题?

由于我没有这些信息,也无法与这些客户交谈,我只能猜测:这是关于可用性的,见上文。

我看到的另一个问题是:

Q2。如果用户一开始就不记得密码,为什么旧密码很重要?

这是可能的答案。 如果你有一只叫“miaumiau”的猫,用她的名字作为密码,但忘记了,你是更愿意被提醒它是什么,还是更愿意被发送像“#zy*RW(ew)”这样的信息?

另一个可能的原因是,用户认为想出一个新密码是一项艰巨的工作!所以,把旧密码发送回去给她一种错觉,让她不用再去做那件痛苦的工作了。

我只是想知道原因。但无论原因是什么,必须解决的是原因而不是原因。

作为用户,我希望事情简单!我不想努力工作!

如果我登录一个新闻网站看报纸,我想输入1111作为密码,然后就可以通过了!!

我知道这是不安全的,但我在乎别人访问我的“帐户”吗?是的,他也会看新闻!

网站是否存储我的“私人”信息? 我今天读的新闻? 那就是网站的问题,不是我的! 站点是否向已验证的用户显示私人信息? 那就先别表现出来!

这只是为了说明用户对问题的态度。

总之,我不认为这是一个如何“安全地”存储纯文本密码的问题(我们知道这是不可能的),而是如何解决客户实际关心的问题。

像往常一样对用户密码进行盐加散列处理。当用户登录时,允许用户的密码(经过salting/hashing),但也允许用户按字面输入匹配。

这允许用户输入他们的秘密密码,但也允许他们输入他们的咸/散列版本的密码,这是某人将从数据库读取的密码。

基本上,让加盐/散列的密码也是一个“明文”密码。

在回答这个问题时,已经有很多关于用户安全问题的讨论,但我想再提一下好处。到目前为止,我还没有看到在系统中存储可恢复密码的合法好处。考虑一下:

通过电子邮件发送密码对用户有好处吗?不。他们从一次性密码重置链接中获益更多,这有望让他们选择一个他们能记住的密码。 在屏幕上显示密码对用户有好处吗?不,原因和上面一样;他们应该选择一个新密码。 让技术支持人员告诉用户密码对用户有好处吗?没有;同样,如果支持人员认为用户的密码请求已经过正确验证,那么为用户提供新密码和更改密码的机会对用户更有利。此外,电话支持比自动密码重置更昂贵,所以该公司也没有受益。

从可恢复的密码中获益的似乎只有那些怀有恶意的人,或者那些需要第三方密码交换的糟糕api的支持者(请永远不要使用这些api !)也许你可以通过如实向客户陈述公司存储可恢复密码没有获得任何好处,只会承担责任来赢得争论。

从这类请求的字里行间,您会发现客户端可能根本不理解,甚至根本不关心密码是如何管理的。他们真正想要的是一个对用户来说并不难的认证系统。所以,除了告诉他们其实他们并不想要可恢复的密码之外,你还应该为他们提供一些让认证过程不那么痛苦的方法,尤其是如果你不需要像银行这样的高安全级别:

允许用户使用他们的电子邮件地址作为用户名。我见过无数用户忘记自己的用户名,但很少有人忘记自己的电子邮件地址。 提供OpenID,让第三方支付用户遗忘的成本。 放宽密码限制。我敢肯定,当一些网站因为“不能使用特殊字符”或“您的密码太长”或“您的密码必须以字母开头”之类无用的要求而不允许您使用首选密码时,我们都非常恼火。此外,如果易用性比密码强度更重要,您甚至可以通过允许更短的密码或不要求混合字符类来放松不愚蠢的要求。随着限制的放松,用户将更有可能使用他们不会忘记的密码。 不要让密码过期。 允许用户重新使用旧密码。 允许用户选择自己的密码重置问题。

但如果你出于某种原因(请告诉我们原因)真的,真的,真的需要一个可恢复的密码,你可以通过给他们一个非密码认证系统来保护用户,以免他们的其他在线帐户受到潜在的威胁。因为人们已经熟悉用户名/密码系统,这是一个行之有效的解决方案,这将是最后的手段,但肯定有很多创造性的替代密码的方法:

让用户选择一个数字引脚,最好不要是4位,最好只在防止暴力尝试的情况下。 让用户选择一个只有他们自己知道的简短答案的问题,这个问题永远不会改变,他们会一直记住,而且他们不介意其他人发现。 让用户输入一个用户名,然后画一个容易记住的形状,并有足够的排列来防止猜测(看看这张G1如何解锁手机的漂亮照片)。 对于一个儿童网站,你可以根据用户名(有点像身份)自动生成一个模糊的生物,并要求用户给这个生物一个秘密的名字。然后他们会被提示输入该生物的秘密名称来登录。