在系统中处理用户帐户管理的最佳方法是什么,而不让您的员工有权访问数据库来访问帐户。
例子:
在数据库中存储用户名/密码。这是一个坏主意,因为任何有权访问数据库的人都可以看到用户名和密码。因此使用它。
存储用户名/密码哈希。这是一种更好的方法,但是可以通过将数据库中的密码哈希替换为您知道其身份验证信息的另一个帐户的哈希来访问该帐户。然后在授予访问权限后将其还原回数据库。
windows/*nix 是如何处理这个问题的?
在系统中处理用户帐户管理的最佳方法是什么,而不让您的员工有权访问数据库来访问帐户。
例子:
在数据库中存储用户名/密码。这是一个坏主意,因为任何有权访问数据库的人都可以看到用户名和密码。因此使用它。
存储用户名/密码哈希。这是一种更好的方法,但是可以通过将数据库中的密码哈希替换为您知道其身份验证信息的另一个帐户的哈希来访问该帐户。然后在授予访问权限后将其还原回数据库。
windows/*nix 是如何处理这个问题的?
这是一种更好的方法,但是可以通过将数据库中的密码哈希替换为您知道其身份验证信息的另一个帐户的哈希来访问该帐户。
真的没有办法解决这个问题。任何对密码文件具有写访问权限的人都可以完全控制计算机。
我会选择2,但使用一些盐。一些伪代码:
SetPassword(user, password)
salt = RandomString()
hash = Hashfunction(salt+password)
StoreInDatabase(user, salt, hash)
CheckPassword(user, password)
(salt, hash) = GetFromDatabase(user)
if Hashfunction(salt+password) == hash
return "Success"
else
return "Login Failed"
使用在库中实现的众所周知的散列函数(例如 MD5 或 SHA-1)很重要。不要自己动手或尝试从书中实现它,这不值得冒出错的风险。
@Brian R. Bondy:您使用盐的原因是为了使字典攻击更加困难,攻击者无法对字典进行哈希处理并尝试对所有密码进行尝试,相反,她必须使用盐 + 字典并对其进行哈希处理,这使得存储需求爆发。如果您有 1000 个最常用密码的字典并对它们进行哈希处理,则您需要 16 kB 之类的大小,但如果添加两个随机字母,您将得到 62*62*16 kB ≈ 62 Mb。
否则,您可以使用某种一次性密码,我听说过有关 OTPW 的好消息,但还没有使用过。
这是多年前 UNIX 中的一个常见问题,通过将用户身份组件(用户名、UID、shell、全名等)与身份验证组件(密码哈希、密码哈希盐)分开来解决。身份组件可以是全局可读的(事实上必须是,如果要将 UID 映射到用户名),但身份验证组件必须保持用户无法访问。要对用户进行身份验证,请拥有一个接受用户名和密码的受信任系统,并返回“已验证”或“未验证”的简单结果。该系统应该是唯一可以访问身份验证数据库的应用程序,并且应该等待一段随机的时间(可能在 0.1 到 3 秒之间),然后再进行回复,以帮助避免定时攻击。
您可以使用 openID 并且根本不保存任何机密用户密码。谁说它只适用于网站?
Jeff Atwood 有一些关于散列的好帖子,如果你决定走那条路:
Unix 将哈希值存储在一个文本文件 /etc/shadow 中,只有特权用户可以访问该文件。密码用盐加密。
您可以将哈希密码的盐存储在另一个表中,当然每个用户都有自己的盐。然后,您可以限制对该表的访问。
通常的方法是将选项二与电子邮件一起使用:
将用户名、密码哈希和电子邮件地址存储到数据库中。
用户可以输入他们的密码或重置密码,在后一种情况下会生成一个随机密码,为用户创建一个新的哈希并通过电子邮件将密码发送给他。
编辑:如果数据库遭到破坏,那么您只能保证无法访问任何敏感信息,您将无法再确保应用程序的安全性。
将用户名和密码散列在一起。这样,如果两个用户的密码相同,哈希值仍然不同。
这对于很多应用程序来说都不是问题,因为获得对数据库的访问权限可能是任何攻击者最常见的目标。那么,如果他们已经可以访问数据库,为什么还要登录应用程序呢?:)
如果“系统”是一个公共网站, RPX可以为您提供最常见的提供商的登录/用户帐户服务,例如 OpenId、Facebook、Google 等。
现在,鉴于您提出问题的方式,我猜您所说的“系统”更可能是基于内部 Windows/Linux 的企业应用程序。尽管如此; 对于那些在谷歌上搜索登录/用户帐户提供商的人(就像我在遇到 RPX 之前所做的那样),这可能是一个很好的选择:)