0

情况是这样的——它与 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 提供的凭据?

4

8 回答 8

4

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

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

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

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


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

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

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

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

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

于 2009-09-12T13:47:43.627 回答
1

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

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

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

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

于 2009-09-12T16:58:50.177 回答
0

你有没有想过像 Stack Overflow 那样接受 OpenID?这样,您根本不负责存储密码。

于 2009-09-12T13:27:46.540 回答
0

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

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

用户名:john,密码:pass

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

md5(username.password.key);

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

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

于 2009-09-12T13:29:32.093 回答
0

只有一种方法可以做到这一点,这对用户来说可能过于繁琐。

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

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

于 2009-09-12T13:30:26.947 回答
0

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

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

编辑

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

于 2009-09-12T13:36:44.117 回答
0

永远不要将密码存储在数据库中,而是存储每个密码的加盐和散列版本

如果这对你来说是中文的,请查看这篇文章。

于 2009-09-12T13:39:06.733 回答
0

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

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

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

--

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

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

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

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

于 2009-09-17T04:02:24.023 回答