【问题标题】:Suggestions on storing passwords in database关于在数据库中存储密码的建议
【发布时间】:2010-11-27 18:11:24
【问题描述】:

情况是这样的——它与 StackOverflow.com 上的其他数据库/密码问题有点不同

我有两组用户。一种是“主要”用户。其他人是“次要”用户。每个人都有我网站的登录名/密码(比如 mysite.com - 这并不重要)。

背景:主要用户可以访问第三个站点(例如 www.something.com/PrimaryUser1)。每个次要用户都“属于”主要用户并希望访问该其他站点的子部分(例如 www.something.com/PrimaryUser1/SecondaryUser1)。

在 mysite.com,主要用户必须向我提供他们用来访问 www.something.com/PrimaryUser1 的凭据,并且他们指定他们选择的次要用户可以访问哪些“子部分”。

Mysite.com 帮助管理次要用户对主要用户站点的子访问。次要用户不能“看到”他们的主要用户的密码,但是通过我的站点,他们可以访问另一个站点的“子部分”——但只能访问他们受限的子部分。

以粗略的方式,我正在实现 OAuth(或类似的东西)。

这里的问题是 - 我应该如何将主要用户的凭据存储到另一个站点?这里的关键点是 mysite.com 使用这些凭据向二级用户提供访问权限,因此它必须能够读取它。但是,我想以这样的方式存储它,让主要用户放心,我(作为网站所有者)无法读取他们的凭据。

我想这更像是一个理论方法问题。密码学领域有什么可以帮助我解决这个问题的吗?


添加的文字:

由于大多数人完全忽略了这个问题,这里尝试#2 来解释它。

PrimaryUser1 拥有 www.something.com/PrimaryUser1Site 的用户名/密码

他希望将子访问权限授予两个人 - SecondaryUser1 和 SecondaryUser2 到文件夹 - www.something.com/PrimaryUser1Site/SecondaryUser1 和 www.something.com/PrimaryUser1Site/SecondaryUser2

Mysite.com 负责此子用户管理,因此 PrimaryUser1 前往那里并向 Mysite.com 提供他的凭据。 MySite.com 在内部使用 PrimaryUser1 提供的凭据为子用户提供有限的访问权限。现在,SecondaryUser1 和 SecondaryUser2 可以通过 MySite.com 访问 www.something.com/PrimaryUser1Site 上各自的文件夹

现在,问题来了,我应该如何存储 PrimaryUser1 提供的凭据?

【问题讨论】:

    标签: sql encryption cryptography oauth passwords


    【解决方案1】:

    您是否考虑过像 Stack Overflow 那样接受 OpenID?这样一来,您根本无需负责存储密码。

    【讨论】:

    • 我确实需要主用户提供第三方网站的密码。
    【解决方案2】:

    有更好的方法来解释这个:(

    但如果您只想知道如何安全地存储密码,请执行以下操作:

    用户名:john,密码:pass

    key = '!!@ijs09789**&*';

    md5(username.password.key);

    当他们登录时,只需检查 md5(username.password.key) = 是否等于数据库中的那个 - 您还可以使用 sha1 或任何其他加密方法。

    http://us.php.net/md5 & http://us.php.net/sha1

    【讨论】:

    • MD5 坏了 - 不要使用它。此外,您应该对哈希进行加盐处理,这样如果两个人的密码相同,您就无法通过查看哈希值来判断。
    • 使用大写用户名,否则用户名区分大小写。
    • 嗨。这个答案没有解决我遇到的问题。据我了解,我必须以我可读的格式存储 PrimaryUser 的密码,以便在 SecondaryUser 登录时授予访问权限。
    • 那么你想要做的,总的来说,是不可能的。
    【解决方案3】:

    只有一种方法可以做到这一点,这对用户来说可能太麻烦了。

    您可以使用公钥/私钥加密用户密码,用户保留他们的密钥,因此只有在将密钥提交回您的服务器时才能解密密码。让这个简单的唯一方法是拥有一些自动提交信息的网络浏览器插件。

    无论哪种方式,您始终可以通过数据包嗅探与服务器之间的通信,因此它仍然毫无意义。

    【讨论】:

      【解决方案4】:

      如果您想自己存储密码,最好的方法是使用单向散列算法,例如 MD5 或 SHA-1。这种方法的优点是 无法从散列值中导出密码。

      您选择的具体算法取决于您使用的精确产品。一些前端工具提供这些功能,一些数据库产品也提供这些功能。否则,您将需要第三方库。

      编辑

      次要用户应该有自己的密码。他们为什么不呢?

      【讨论】:

        【解决方案5】:

        切勿将密码存储在数据库中,而是存储每个密码的加盐和散列版本

        如果这是你的中文,请查看article

        【讨论】:

          【解决方案6】:

          第一条规则:永远不要存储密码! 第二条规则:计算密码的哈希值,加上额外的盐,并将其存储在您的数据库中。 第三条规则:用户名(大写)可以用作盐,但最好多加一点盐! (一些额外的文字,最好是长的。) 第四条规则:不管哈希算法有多安全,它们迟早都会被黑客入侵。只需要时间! 第五条规则:您网站的安全性取决于其背后的价值。内容价值越高,被攻击的可能性就越大! 第六条规则:你迟早会发现你的网站被黑了,但不是通过被黑的密码,而是通过代码中其他地方的漏洞。最大的风险是期望您的网站是安全的,因为您已经实施了一些强大的安全性。 第七条规则:所有安全都可以被破坏,所有网站都可以被黑客入侵,你所有的秘密都可以被发现,只要人们愿意投入足够的时间来这样做。

          安全是一种幻想,但只要没有人打破它,您就可以继续梦想!时刻准备好迎接艰难的觉醒,这将需要你再次重建你的幻觉。 (换句话说,定期备份!(最好每天备份。)不要覆盖上周的备份,并确保每周至少保留一份备份,以防万一你发现你的网站在几个月前被黑客入侵了从那以后你的备份被感染了!

          现在,如果您确实需要存储密码,请使用用户名加密码的哈希值。然后用哈希加盐再次哈希!更好的是,创建一个盐列表(只是单词列表),每当创建一个新用户帐户时,选择一个随机盐词用于散列他的用户名和密码。将盐的索引与用户帐户一起存储,这样您就知道在他再次登录时要使用哪个。

          并且: 八法则:始终使用HTTPS!它不像大多数人那样安全,但它确实给您的用户一种安全感!


          既然你已经添加了文字,我会添加更多的答案。

          由于您希望 user1 向用户 2 授予临时访问权限,因此您需要一个辅助用户表。 (或者使用父用户 ID 扩展用户表。还添加一个时间戳来跟踪帐户年龄。用户 1 可以创建凭据,这是以正常方式完成的。只需存储一个包含用户名和盐组合的哈希。在在这种情况下,使用用户 1 的用户名作为额外的盐!只要确保在用户 1 注销或经过一定时间后禁用用户 2 帐户。并允许用户 1 再次启用所有帐户他创建的,因此他们可以重复使用帐户,而不必一直创建新帐户。

          安全性不取决于主要或次要用户。一般来说,以同样的方式对待它们!二级用户有一个额外的好处,您可以使用主帐户作为额外的盐。其余部分与身份验证无关。这是您正在处理的授权。虽然身份验证和授权有着密切的关系,但请注意,您应该将它们视为两种不同的独立技术。

          当用户 1 登录时,他被授予访问主站点的权限。当他授予用户 2 访问权限时,用户 2 将获得一组减少的角色。但这与存储用户名或密码无关。您只有一个用户 ID,它恰好是某些角色或组的成员。或者不是,但那些将无法访问。

          他们都只是用户,一个比另一个拥有更多权限。

          【讨论】:

            【解决方案7】:

            这取决于您的主站点和辅助站点同意的身份验证类型。它是形成身份验证、HTTP Basic 还是 HTTP Digest?如果是forms 或basic 那么你别无选择,你必须存储密码,所以你唯一的选择就是加密它。您不能存储密码哈希,因为您必须在表单和 HTTP Basic 的身份验证期间显示明文。存储加密密码产生的问题是由于密码使用不正确(即您没有使用 IV 或盐,或者您没有正确使用流密码),但更重要的是您将拥有密钥管理问题(在哪里存储用于加密密码的密钥以及如何从非交互式服务/恶魔访问它)。

            如果第 3 方站点接受 HTTP Digest,那么您的运气会更好,您可以存储 Digest 哈希的 HA1 hash 部分(即 username:realm:password 的 MD5),因为您可以直接从HA1。

            我没有说明用户如何配置辅助凭据(即,您首先如何获取辅助站点用户名和密码),我假设您已经保护了一个受保护的通道(即从客户端到主站点的 HTTPS )。

            顺便说一句,这假定身份验证发生在您的主站点和辅助站点之间,并且辅助站点内容通过对主站点发出的 HTTP 请求进行隧道传输。如果不是这种情况并且辅助站点实际上是直接从浏览器访问的,那么辅助站点必须支持某种基于预认证令牌的第三方授权,例如 OAuth。在浏览器实际需要凭据的情况下,依靠凭据身份验证并将凭据存储在主站点上存在很多问题,甚至不值得讨论。

            【讨论】:

              【解决方案8】:

              你把它弄得太复杂了。您需要停止尝试混合身份验证和授权。

              您要做的是为每个人建立凭据,此时不必担心他们是“主要”用户还是“次要”用户。然后在您管理用户和主要/次要关系的主站点上,您可以执行哪些用户是主要或次要用户的逻辑,并将所有这些内容存储在一个表中。每当主要用户更新他们与他们的关系时,您授予或拒绝您希望每个次要用户的任何权利和子权利。完成后,您最终需要将适当的用户凭据从主站点复制到辅助站点。

              然后,当次要用户想要访问您农场中的任何站点时,他们只会以自己的身份进行身份验证 - 他们永远不会冒充主要用户!当主要用户授予他们“次要”身份时,他们只有您授予他们的权利。

              --

              好的,既然您在评论中击落了该解决方案,请考虑一下:

              首先,我怀疑任何事情都不会真正安全。如果您监控用户的活动,您始终可以恢复秘密。

              现在,这完全是即兴的,我还没有对其进行密码分析,但请检查一下所谓的secret sharing 方案。将“有效”或“真实”的主站点主用户密码存储为共享密钥。使用主要用户提供的密码的加盐哈希作为一个秘密。使用第一个辅助用户提供的密码的加盐哈希作为另一个秘密,对于每个额外的辅助用户,依此类推。不要存储盐渍哈希!只需存储盐和受保护的共享密钥。

              当用户输入他们的密码时,您检索受保护的共享密钥,使用他们密码的盐和散列生成加盐散列,解密受保护的共享密钥,现在您已经获得了原始的主用户密码。

              【讨论】:

              • 嗨,jadeders - 你错过了主要的观点......次要用户必须“冒充”主要用户才能访问该资源。没有其他办法。我试图找出的是,是否有任何密码学框架可以帮助我以我无法读取的方式存储主要用户的密码。请记住:当次要用户想要访问它时,我必须将其提供给另一个站点......可以设计一些东西,以便我只能在次要用户登录时“访问”存储的密码,而我不能直接访问? ......似乎不可能,不是吗? :D
              猜你喜欢
              • 2014-07-17
              • 2018-07-27
              • 1970-01-01
              • 1970-01-01
              • 2011-03-30
              • 1970-01-01
              • 2020-03-20
              • 2011-06-10
              • 2011-10-24
              相关资源
              最近更新 更多