实现用户登录系统的正确方式

20

我想为了学习制作一个用户登录系统,进行了一些研究后发现正确的实现方式是在数据库中存储用户名/ID和密码的加密/哈希版本。当用户登录时,密码会在客户端进行加密(MD5,SHA-1等),然后发送到服务器进行比对。如果匹配成功,则用户可以成功登录。

这种实现方法可以防止数据库管理员或程序员查看数据库中明文密码。同时也能够防止黑客窃取传输中的真实密码。

以下是我困惑的地方:

  1. 如果黑客通过攻击数据库获得了密码的哈希值/加密版本,或者数据库管理员、程序员只需简单地读取数据库中的文本即可获得密码的哈希版本,他们可以轻松地编写程序将该哈希版本的密码发送到服务器以成功登录。如果能够这样做,那么加密密码似乎就没有多大用处。我觉得我可能有什么误解。

  2. 这种实现用户登录功能的方式是否最受欢迎?它是否符合当前的最佳实践?我是否必须手动完成所有操作,还是某些数据库具有内置功能以执行相同的操作?如果有,请提供详细信息。

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

  4. 这种方式(第3点)是否足以保证正常使用的安全性?其他数据库系统如MySQL是否具有此类功能以执行相同操作?如果是,那么使用MySQL内置方法是否足够安全?

我不是在寻找一个非常超级安全的实现用户登录功能的方式,而是希望能够找到一种流行、易于实现、适当并且对大多数Web应用程序来说足够安全的方式。请给我一些建议。真诚感谢提供的详细信息。

2个回答

18
当用户登录时,客户端代码将使用MD5或SHA-1等算法加密密码,然后发送给服务器端,并与数据库中的密码进行比较。如果匹配成功,则用户成功登录。 但是,不,不,客户端需要发送未经哈希处理的密码。如果您在客户端上对密码进行哈希处理,那么哈希处理实际上就是密码。这将使密码的加密哈希失去意义。必须在服务器端进行哈希处理。 为了在传输过程中保护明文密码,需要通过安全通道发送,例如加密的TLS(SSL)连接。

密码应该使用一些额外的数据进行盐值处理,每个账户的数据都应该不同。盐的存在可以通过消除明文和哈希之间的直接关联来防止彩虹表攻击。盐值不需要保密,也不需要非常大。即使只有4个随机字节的盐值也将使彩虹表攻击的复杂度增加40亿倍。


目前业界的黄金标准是Bcrypt。除了加盐外,bcrypt通过设计减速因子来增加安全性。

除了采用盐以防止彩虹表攻击外,bcrypt还是一种自适应函数:随着时间的推移,迭代次数可以增加以使其变慢,因此即使计算能力不断增强,它仍然抵抗暴力搜索攻击......从密码理论上讲,这并不比标准的Blowfish密钥调度更强大,但重新调整密钥轮数的数量是可配置的;因此,这个过程可以被任意地放慢,这有助于防止对哈希或盐进行暴力攻击。


1
如果一个系统在客户端使用公共盐值对密码进行哈希,然后在服务器端使用私有盐值(即存储在服务器上的字符串或服务器端随机生成的盐值)重新哈希密码,那会怎样呢?这样,服务器将永远不会知道实际的明文密码,也不会发送明文密码到服务器以供黑客获取。我知道,中间人仍然可以获取密码哈希,并尝试使用JavaScript中的盐值进行暴力破解,但是,这仍然会使他的生活变得相当困难,不是吗? - Adam Baranyai
如果客户端向服务器发送了一个哈希密码,那么哈希密码实际上就是真正的密码。如果黑客截获了哈希密码,他们可以将其发送到服务器而不知道原始的未经哈希处理的密码,服务器将接受它。 - John Kugelman
4
但是这也适用于以明文形式发送到服务器的密码。如果黑客截取了它,它可以直接使用该密码登录帐户。但是,如果将明文密码进行哈希处理,即使黑客截取了哈希值,他只能登录到特定的网站,而不能登录到客户可能使用相同密码的任何其他网站。 - Adam Baranyai

4
一些澄清:
  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. 不要使用数据库内置的安全功能来处理登录。这是很容易被攻击的,也会给他们比他们应该拥有的更多应用程序访问权限。使用表格。
  5. 您没有提及SSL。即使是设计良好的身份验证系统,如果密码以明文形式通过网络发送,也是无用的。还有其他方法,如挑战/响应,但不幸的是,当用户注册或更改密码时,密码仍必须以明文形式发送到服务器。SSL是防止此类问题的最佳方法。

不要使用像SHA这样的快速哈希算法来处理密码。这会使攻击者更容易地对密码进行暴力破解。相反,应该使用专门为密码哈希设计的“密码哈希”算法,如bcryptscryptargon2 - ryboe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接