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

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

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

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

Bounty的其他信息

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

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

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

谢谢大家

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

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

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


当前回答

密码遗失/忘记处理:

没有人能够恢复密码。

如果用户忘记了密码,他们至少必须知道自己的用户名或电子邮件地址。 根据请求,在Users表中生成GUID,并向用户的电子邮件地址发送包含GUID作为参数的链接的电子邮件。

链接后面的页面验证参数guid是否真的存在(可能带有一些超时逻辑),并要求用户输入新密码。

如果您需要热线帮助用户,请向授予模型中添加一些角色,并允许热线角色临时以已识别的用户登录。记录所有此类热线登录。例如,Bugzilla为管理员提供了这样的模拟功能。

其他回答

想象一下,有人委托建造一座大型建筑——比方说一座酒吧——下面的对话发生了:

建筑师:对于这种规模和容量的建筑,这里、这里和这里都需要安全出口。 客户:不,那太复杂了,维护起来也太贵了,我不想要任何侧门或后门。 建筑师:先生,消防出口不是可有可无的,这是城市消防法规规定的。 客户:我付你钱不是让你争辩的。照我说的做。

建筑师是否会问如何在没有安全出口的情况下合乎道德地建造这栋建筑?

在建筑和工程行业,对话很可能是这样结束的:

建筑师:这栋建筑没有安全出口是建不起来的。你可以去找其他有执照的专业人士,他会告诉你同样的事情。我现在要走了;等你准备好合作了再打给我。

计算机编程可能不是一个有执照的职业,但人们似乎经常想知道为什么我们的职业没有得到与土木或机械工程师同样的尊重——好吧,不用再看了。这些职业,当遇到垃圾(或完全危险的)要求时,会简单地拒绝。他们知道这不是一个借口,“嗯,我尽力了,但他坚持,我必须按他说的做。”他们可能会因此被吊销执照。

我不知道您或您的客户是否是任何上市公司的一部分,但以任何可恢复的形式存储密码都会导致您无法通过几种不同类型的安全审计。问题不在于某些进入数据库的“黑客”要恢复密码有多难。绝大多数安全威胁来自内部。你需要防止的是一些心怀不满的员工拿走所有的密码,然后把它们卖给出价最高的人。使用非对称加密和将私钥存储在单独的数据库中绝对不能防止这种情况;总有人可以访问私人数据库,这是一个严重的安全风险。

没有道德或负责任的方式以可恢复的形式存储密码。时期。

不要放弃。你可以用来说服你的客户的武器是不可否认性。如果你可以通过任何机制重建用户密码,你就给了他们的客户一个合法的不可抵赖机制,他们可以拒绝任何依赖于该密码的交易,因为供应商无法证明他们没有重建密码并自己完成交易。如果密码被正确地存储为摘要而不是密文,这是不可能的,因此最终客户要么自己执行交易,要么违反了他对密码的注意义务。无论哪种情况,责任完全落在他身上。我处理过的案件中,金额高达数亿美元。不是你想出错的事。

我认为你真正应该问自己的问题是:“我怎样才能更好地说服别人?”

您可以使用公钥加密密码+盐。对于登录,只需检查存储的值是否等于从用户输入+ salt计算的值。如果需要以明文形式恢复密码,则可以使用私钥手动或半自动地解密。私钥可以存储在其他地方,还可以对称加密(这将需要人工交互来解密密码)。

我认为这实际上有点类似于Windows恢复代理的工作方式。

密码被加密存储 人们无需解密为明文即可登录 密码可以恢复为明文,但必须使用私钥,私钥可以存储在系统之外(如果您愿意,可以存储在银行保险箱中)。

出于道德考虑,您不能为以后的明文检索存储密码。就这么简单。就连乔恩·斯基特(Jon Skeet)也不能在道德上存储密码以供以后的明文检索。如果您的用户可以以某种方式以纯文本检索密码,那么黑客也可能会在您的代码中发现安全漏洞。这不仅仅是一个用户的密码被泄露,而是所有用户的密码都被泄露了。

如果你的客户对此有意见,告诉他们可恢复的存储密码是违法的。无论如何,在英国,《1998年数据保护法》(特别是附表1,第II部分,第9段)要求数据控制者使用适当的技术措施来保证个人数据的安全,除其他外,考虑到如果数据被泄露可能造成的损害——这对于在不同网站之间共享密码的用户来说可能是相当大的。如果他们仍然无法理解这是一个问题,给他们举一些现实世界的例子,比如下面这个。

允许用户恢复登录的最简单方法是通过电子邮件向他们发送一个一次性链接,该链接可以自动登录,并直接将他们带到一个可以选择新密码的页面。创建一个原型,并展示给他们看。

以下是我写的几篇关于这个主题的博客文章:

http://jamesmckay.net/2009/09/if-you-are-saving-passwords-in-clear-text-you-are-probably-breaking-the-law/ http://jamesmckay.net/2008/06/easy-login-recovery-without-compromising-security/

更新:我们现在开始看到针对未能正确保护用户密码的公司的诉讼和起诉。例子:领英(LinkedIn)遭到500万美元的集体诉讼;索尼因PlayStation数据泄露被罚款25万英镑。如果我没记错的话,LinkedIn实际上对用户的密码进行了加密,但它使用的加密技术太弱了,不太有效。