【问题标题】:Best way to handle user account authentication and passwords处理用户帐户身份验证和密码的最佳方法
【发布时间】:2010-09-08 19:31:09
【问题描述】:

在不让有权访问数据库的员工访问帐户的情况下,在系统中处理用户帐户管理的最佳方法是什么。

例子:

  1. 在数据库中存储用户名/密码。这是一个坏主意,因为任何有权访问数据库的人都可以看到用户名和密码。因此使用它。

  2. 存储用户名/密码哈希。这是一种更好的方法,但是可以通过将数据库中的密码哈希替换为您知道其身份验证信息的另一个帐户的哈希来访问该帐户。然后在授予访问权限后将其还原回数据库。

windows/*nix 是如何处理这个问题的?

【问题讨论】:

    标签: security database-design authentication authorization


    【解决方案1】:

    您可以将散列密码的 salt 存储在另一个表中,当然每个用户都有自己的 salt。然后,您可以限制对该表的访问。

    【讨论】:

      【解决方案2】:
      1. 确实是个非常糟糕的主意。如果数据库遭到入侵,所有帐户都会遭到入侵。
      2. 好方法。如果您的哈希算法包含用户名,则将密码哈希替换为另一个将不起作用。

      Unix 将哈希值存储在一个文本文件 /etc/shadow 中,只有特权用户可以访问该文件。密码用盐加密。

      【讨论】:

      • 有权访问数据库的人仍然可以访问该帐户。他们只需要临时重命名用户名。
      • 那么您可以通过移动该文件中的密码哈希来交换 2 个用户的密码吗?
      • Brian,如果哈希算法包含用户名,则不是。
      【解决方案3】:

      这是一种更好的方法,但是可以通过将数据库中的密码哈希替换为您知道其身份验证信息的另一个帐户的哈希来访问该帐户。

      真的没有办法解决这个问题。任何对密码文件具有写访问权限的人都可以完全控制计算机。

      【讨论】:

        【解决方案4】:

        您可以使用 openID 并且完全不保存任何机密用户密码。谁说它只适用于网站?

        【讨论】:

          【解决方案5】:

          我会选择 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:你使用 salt 的原因是为了让字典攻击更加困难,攻击者不能对字典进行哈希处理并尝试对所有密码进行哈希处理,相反,她必须使用 salt + 字典并对其进行哈希处理,这使得存储需求爆炸。如果您有 1000 个最常用密码的字典并对它们进行哈希处理,则需要 16 kB 之类的大小,但如果添加两个随机字母,您会得到 62*62*16 kB ≈ 62 Mb。

          否则你可以使用某种One-time passwords 我听说过关于 OTPW 的好消息,但还没有使用过。

          【讨论】:

          • 如果盐也存储在数据库中,使用盐有什么好处吗?
          • 同意,但如果 SHA-1 可用,我建议不要使用 MD5。 MD-5 的漏洞有据可查——SHA-1 “更好”。
          • +1 大喊不要编写自己的加密算法 :-)
          【解决方案6】:

          通常的方法是在电子邮件中使用选项二:

          将用户名、密码哈希和电子邮件地址存储到数据库中。

          用户可以输入密码或重置密码,在后一种情况下会生成一个随机密码,为用户创建一个新的哈希值并通过电子邮件将密码发送给他。

          编辑:如果数据库被入侵,那么你只能保证不能访问任何敏感信息,你不能再保证你的应用程序的安全。

          【讨论】:

            【解决方案7】:

            散列用户名和密码一起。这样,如果两个用户的密码相同,哈希值仍然会不同。

            【讨论】:

              【解决方案8】:

              Jeff Atwood 有一些关于散列的好帖子,如果你决定走这条路:

              【讨论】:

                【解决方案9】:

                这是多年前 UNIX 中的一个常见问题,通过将用户身份组件(用户名、UID、shell、全名等)与身份验证组件(密码哈希、密码哈希盐)分开来解决。身份组件可以是全局可读的(事实上必须是,如果要将 UID 映射到用户名),但身份验证组件必须保持用户无法访问。要对用户进行身份验证,请拥有一个接受用户名和密码的受信任系统,并返回“已验证”或“未验证”的简单结果。该系统应该是唯一可以访问身份验证数据库的应用程序,并且应该等待一段随机的时间(可能在 0.1 到 3 秒之间),然后再进行回复,以帮助避免定时攻击。

                【讨论】:

                  【解决方案10】:

                  这对很多应用程序来说都不是问题,因为获得对数据库的访问权限可能是任何攻击者最常见的目标。那么,如果他们已经可以访问数据库,为什么还要登录应用程序呢? :)

                  【讨论】:

                  • 适用于很多应用程序。不是我的。有时数据库会引用磁盘上的文件。有权访问数据库并不能访问磁盘上的文件。
                  【解决方案11】:

                  如果“系统”是公共网站RPX 可以为您提供最常见的提供商的登录/用户帐户服务,如 OpenId、Facebook、Google 等。

                  现在,鉴于您提出问题的方式,我猜您所说的“系统”更可能是基于内部 Windows/Linux 的企业应用程序。尽管如此;对于那些在谷歌上搜索登录/用户帐户提供商的人(就像我在遇到 RPX 之前所做的那样),这可能是一个很好的选择:)

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2013-08-27
                    • 2020-04-18
                    • 1970-01-01
                    • 2018-06-23
                    • 2015-05-23
                    • 2011-10-05
                    • 2017-07-31
                    • 1970-01-01
                    相关资源
                    最近更新 更多