【问题标题】:How to manage passwords in web applications?如何管理 Web 应用程序中的密码?
【发布时间】:2011-03-16 03:25:53
【问题描述】:

在 Web 应用程序中持久保存用户密码的当前最先进的方法是什么?我正在使用 Java 6 + MySQL。我想到的一些问题是:在应用程序中编码还是通过 DBMS 编码更好(这是否相关)?哪种算法被认为是可靠的?在数据库中存储什么?对这些东西真的很陌生,所以可能错过了一些关键细节,在这种情况下,请随时告诉我。

谢谢。

【问题讨论】:

  • 我认为通用框架在客户端或服务器端对密码进行哈希处理并将哈希存储在数据库中。这个哈希值是在数据库被入侵的情况下。

标签: java mysql passwords password-protection


【解决方案1】:

您应该将安全散列加盐版本的密码存储到数据库中。这样一来,如果您的网站遭到黑客入侵,由于用户几乎在任何地方都使用相同的通行证,因此他们的其他帐户不会被盗用。

为此,应做到以下几点:

  1. 使用尚未破解的安全散列算法(最好是 SHA-512,Sha1 和 MD5 已破解
  2. 连接 Username+Password+Salt(salt 应该是一个相对较长的常量字符串,在您的应用程序中始终保持不变,并且可以防止彩虹攻击)
  3. 连接的SHA-512结果并将其存储在数据库中。
  4. 每次用户尝试登录时,使用相同的方法散列他/她的凭据并检查数据库中的数据,如果相同,则其正确。

在哪里散列密码(应用程序或数据库)并不重要,但数据库的安全散列功能有限,因此应用程序是更好的选择。

【讨论】:

  • -1:您想要一个盐每个哈希,而不是每个应用程序。这使彩虹表的生成变得非常复杂。每个应用程序的盐没有多大作用。一个常用词的彩虹表可以在一天左右的时间内计算出来。
  • @WhiteFang34:这毫无意义。攻击者可以简单地使用散列密码伪造请求并获得访问权限。
  • @AbiusX:知道你的盐,我可以简单地生成 ONE 彩虹表并检查你所有的密码。你的盐的长度不会让我更难生成彩虹表。此外,如果我可以访问您的数据库,我也可以访问您存储“安全盐”的代码。这不会发生在按密码加盐的情况下。我必须为每个密码生成一个彩虹表,这在时间上很昂贵(使用像bcrypt 这样的慢速算法甚至更昂贵)。
  • @AbiusX - 不,这不是强制性的。事实上,任何类型的腌制都不是强制性的。哎呀,即使散列也不是强制性的。我们可以只以纯文本形式存储密码。另一方面,散列比纯文本更安全,所以它会更可取。并且加盐哈希更安全一些,所以它可能也是可取的。并且看到每个密码散列使用不同的盐进行加盐处理比根据预期了解安全性的人使用恒定的长盐进行加盐处理更可取,那么合乎逻辑的结论难道不是 确实更安全吗?跨度>
  • @AbiusX - 是的,这也是真的。这是你想要如何花费你的努力的呼吁。这仍然没有使@Andrew 错误地提出他的建议,即每个密码使用一个盐比对所有密码使用单个长盐提供更多的安全性。
【解决方案2】:

bcrypt 是一种可靠的密码散列算法。它是由具有安全意识的安全专业人员创建的。

bcrypt 很慢(这是一件好事,使得创建彩虹表的成本非常高)。您可以配置 bcrypt 以使用可变数量的轮数来扩展您使用的任何硬件(更多轮数 = 更慢)。此外,它会自动处理盐生成,每个散列不同的盐(这使得彩虹表攻击几乎不可能,因为bcrypt 的缓慢性质以及每个密码需要一个完整的彩虹表的事实)。

bcrypt 的 Java 实现可在 jBCrypt 获得。

【讨论】:

    【解决方案3】:

    您将面临许多自称安全专家的愤怒,因为他们提出了这样的问题。我自己不是安全专家,但我觉得自己有足够的资格在常识的驱动下提出一些建议。根据您希望应用程序的安全程度,有多种方法。

    1- 大多数攻击发生在您通过网络传输凭据时。 (中间的人)。因此,您需要确保用户名和密码的传输是安全的。 (ssl 或 HTTP 摘要)。如果安全性非常重要,那么您应该探索是否需要传递用户名\密码。 (通过使用一些基于令牌的身份验证,如 Oauth 而不是用户名和密码)

    2- 如果您决定传入用户名和密码,则需要在您的应用程序范围内缩短密码字符串的生命周期。当然,最好的方法是实现基于 LDAP 等机制的身份验证过滤器。大多数 LDAP 存储,将允许您存储加密密码并允许您通过绑定执行身份验证。(因此您的应用程序将永远不会担心身份验证和存储)

    3- 如果您确实将密码带到了应用程序层,当然您仍然需要减少明文密码的生命周期并使用一些安全的散列算法进行加密。但是这种方法并将密码存储在数据库中(即使是加密形式)并不是那么安全。 (特别是,由于您正在存储密码,因此有人可以绕过您的安全层)

    因此,总而言之,根据您需要的安全程度,您需要问自己以下问题。

    1- 您是否需要发送用户名/密码?

    2- 你能确定密码不能通过网络被嗅探吗?

    3- 您能否不将您的身份验证委托给前端过滤器,而不是委托给您的应用程序层?

    【讨论】:

    • 恐怕我跑题了。但简单的答案是“不要在你的 rdbms 存储中保存密码”。将此委托给前端过滤器。 (如果是 java 应用程序服务器 jaas,或者像 ldap 这样的商店支持的 spring security 等库)
    猜你喜欢
    • 2011-03-07
    • 2016-01-04
    • 2018-01-28
    • 2015-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-14
    相关资源
    最近更新 更多