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

Posted

技术标签:

【中文标题】实现用户登录系统的正确方法【英文标题】:The proper way of implementing user login system 【发布时间】:2013-07-31 06:17:53 【问题描述】:

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

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

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

这是我感到困惑的地方:

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

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

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

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

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

【问题讨论】:

【参考方案1】:

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

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

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


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


目前的行业黄金标准是 Bcrypt。除了加盐之外,bcrypt 通过设计减速因素来进一步提高安全性。

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

【讨论】:

如果系统使用公共盐对密码客户端进行哈希处理,然后使用私有盐(即存储在服务器上的字符串或随机生成的盐)重新哈希密码服务器端怎么办?在服务器端)?这样,服务器永远不会知道实际的纯文本密码,也不会在任何时候将密码的纯文本版本发送到服务器以供黑客获取。我知道,中间人仍然可以获取密码哈希,并尝试用 javascript 中的盐来强制它,但是,这仍然会让他的生活变得更加艰难,不是吗? 如果客户端向服务器发送散列密码,那么散列密码实际上就是真正的密码。如果黑客截获了散列密码,他们可以在不知道原始未散列密码的情况下将其发送到服务器,并且服务器会接受它。 是的,但是发送到服务器的纯文本密码也是如此。如果黑客拦截了它,它可以简单地使用它来登录帐户。然而,如果对纯文本密码进行哈希处理,如果黑客拦截了该密码,他只能登录该特定网站,而不能登录客户端可能具有相同密码的任何其他网站。【参考方案2】:

一些澄清:

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

【讨论】:

以上是关于实现用户登录系统的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

java单点登录

使用 JSF 2.0 实现重定向登录的正确方法是啥?

ssm实验室座位管理系统的设计与实现

JavaWeb基于AD域的单点登录怎么做?

找出用户是不是在 MVC WEB API 中登录的正确方法是啥?

Spring Boot 实现登录拦截器,这才是正确的姿势!!