18

我想做一个用户登录系统,用于学习。我有几个问题。

我做了一些研究,发现实现用户登录系统的正确方法是将用户名/id和密码的加密/哈希版本存储在数据库中。当用户登录时,密码在客户端加密(MD5、SHA-1 等)并发送到服务器,与数据库中的密码进行比较。如果它们匹配,则用户成功登录。

此实现可防止 DBA 或程序员看到数据库中密码的明文。它还可以防止黑客在传输过程中截获真实密码。

这是我感到困惑的地方:

  1. 如果黑客知道密码的哈希/加密版本(通过破解数据库)或 DBA,程序员只需读取数据库中的文本即可获得密码的哈希版本。然后,他们可以轻松地制作一个程序,将这个散列版本的密码发送到服务器,从而使他们能够成功登录。如果他们能做到这一点,加密密码似乎不是很有用。我想我在这里误解了一些东西。

  2. 这是(我上面描述的方式)实现用户登录功能的最流行的方式吗?它是否遵循当前的最佳实践?我是否必须手动完成所有操作,或者某些数据库是否具有执行相同操作的内置功能?对于网站或网络应用程序,是否有最常见的方式/方法?如果是这样,请向我提供详细信息。

  3. 我以前的公司使用 couchDB 存储用户登录信息,包括密码。他们并没有在加密方面做太多事情。他们说couchDB会自动加密密码并将其存储在文档中。我不确定这是否是一种安全的方式。如果是这样,那么它对程序员来说非常方便,因为它可以节省大量工作。

  4. 这种方式(第 3 点)对于正常使用是否足够安全?其他数据库系统比如 mySQL 有这种能力可以做同样的事情吗?如果是这样,是否意味着使用 mySQL 内置方法就足够安全了?

我不是在寻找一种非常安全的方式来实现用户登录功能。我宁愿寻找一种流行的、易于实现的、适当的、对大多数 Web 应用程序足够安全的方法。请给我一些建议。提供的详细信息将不胜感激。

4

2 回答 2

16

当用户登录时,客户端代码会通过 MD5 或 SHA-1 或类似的方式对密码进行加密,然后将此加密后的密码发送到服务器端,然后将其与数据库中的密码进行比较。如果匹配,则用户登录成功。

不,不,客户端需要发送未散列的密码。如果您在客户端散列密码,那么该散列实际上就是密码。这将使加密散列的安全性无效。散列必须在服务器端完成。

为了保护传输中的明文密码,需要通过安全通道发送,例如加密的 TLS (SSL) 连接。


密码应该用每个帐户不同的额外数据加盐。加盐通过消除明文和哈希之间的直接相关性来抑制彩虹表攻击。盐不需要保密,也不需要非常大。即使是 4 个随机字节的盐也会使彩虹表攻击的复杂性增加 40 亿倍。


现在的行业黄金标准是Bcrypt。除了加盐之外,bcrypt 还通过设计减速因素来增加安全性。

除了加入盐来防止彩虹表攻击之外,bcrypt 还是一个自适应函数:随着时间的推移,可以增加迭代次数以使其变慢,因此即使在计算能力增加的情况下,它仍然可以抵抗暴力搜索攻击......加密理论上,这并不比标准的 Blowfish 密钥调度强,但密钥更新轮数是可配置的;因此,这个过程可以任意变慢,这有助于阻止对哈希或盐的暴力攻击。

于 2013-07-30T22:12:37.580 回答
5

一些澄清:

  1. 不要使用 MD5。它被认为是坏的。使用 SHA,但我会推荐比 SHA1 更好的东西。- https://en.wikipedia.org/wiki/MD5
  2. 你没有提到任何关于加盐密码的事情。这对于防止彩虹表至关重要。- https://en.wikipedia.org/wiki/Rainbow_tables
  3. 加盐/散列密码的想法并不是真正保护您自己的应用程序。这是因为大多数用户都有一些用于许多网站的密码。散列/加盐可防止任何有权访问您的数据库的人了解这些密码是什么,并使用它们登录他们的银行应用程序或类似的东西。一旦有人直接访问数据库,您的应用程序的安全性就已经完全受到威胁。- http://nakedsecurity.sophos.com/2013/04/23/users-same-password-most-websites/
  4. 不要使用数据库的内置安全性来处理您的登录。这很 hacky,并且给了他们比他们应该拥有的更多的应用程序访问权限。使用一张桌子。
  5. 您没有提及有关 SSL 的任何内容。如果密码以纯文本形式通过网络发送,即使设计良好的身份验证系统也毫无用处。还有其他方法,例如挑战/响应,但不幸的是,当用户注册或更改密码时,密码仍然必须以纯文本形式发送到服务器。SSL 是防止这种情况的最佳方法。
于 2013-07-30T22:14:01.587 回答