如何为Web应用程序实现登录系统?

15

我正在为一个网站编写登录系统。
以下是我实现登录系统的核心内容:

我有两个表:用户和会话。

   users: uid | uname | pass
sessions: sid | uid | ts | ts_expires

用户输入用户名和密码组合。

  • 如果组合不正确,我将重定向到“bad auth”页面。
  • 如果组合正确,我会:
    • 生成一个随机的sid(sessionid)
    • 插入一条记录到sessions中,将该sid与提供的用户名的uid相关联。
    • 设置一个名为sid的cookie,其中包含刚刚插入到sessions中的随机sid的值。

在需要用户登录的每个页面上,我检查:

  • 是否设置了cookie
  • 如果sid有效

所以我的问题是:

  • 这种机制可能存在什么问题?
  • 如何实现良好的登录系统?

附:我尚未使用SSL安全登录。所以,截至目前,这是唯一的问题。哦,我使用php和mysql,如果有相关的话。


编辑:我将密码存储为用户名与密码连接的MD5。

因此,pass = MD5($uname.$pass)


MD5 可能容易受到暴力破解攻击。为了更好的安全性,应该使用不同的盐值进行多次哈希。使用用户名作为盐值并不是一个很好的想法,因为这个值是潜在攻击者已知的。 - Adam Crossland
那么您的意思是我应该使用随机盐进行哈希,并将盐与用户名/密码一起存储在用户表中,对吗? - jrharshath
正确。盐也可以是明文。 - Malfist
对于盐+哈希循环的多次迭代,您可以通过计算置换盐来实现。 - Adam Crossland
1
关于密码存储:有一个公共标准,PKCS#5(也称为RFC2898),用于处理密码哈希。 符合该标准将是密码存储的良好起点。 - atk
@atk很好的选项清单,我有哪些选择,谢谢。 - jrharshath
4个回答

18

使用盐值对密码进行哈希加密!使用像bcrypt这样的强哈希算法。如果不得不使用MD5/SHA,使用一种叫做“拉伸”(stretching)的技术,并将其哈希数千次。用户不在乎检查密码需要花费1秒还是1/1000秒,但暴力破解者会在意。

记录尝试并防止暴力破解尝试。

非常小心存储用户登录后的凭据的位置。您不希望他们更改它。

并使用SSL!


我还建议您在客户端和服务器端手动使用RSA对所有发送的数据进行编码,以提高安全性。您永远不知道黑客可能会用您的魔兽世界物品统计信息做什么。 - Kornel Kisielewicz

3
为了减缓暴力攻击的速度,在尝试登录失败后增加强制延迟;也就是说,如果有人输入了错误的密码,则在显示“密码错误”之前等待三秒钟。

这会潜在地减缓我的网站吗? - jrharshath
2
不是真的。如果它是一个睡眠,它不会消耗时钟周期,只会延迟网页加载对于那个人。 - Malfist

2

通常最好的做法是将密码存储为实际密码的加盐单向哈希值,而不是以明文形式存储。您没有说明是否这样做了,如果没有,请这样做。

确保登录具有超时期限,以便它不会永久存在。

确保在注销时删除cookie。

不要忘记用户可能从公共计算机登录,并且将登录凭据存储为cookie可能导致后续用户通过废弃的会话获得访问权限。


1
关于最后一点(公共计算机):我只能警告用户不要在公共计算机上使用“记住我”功能,对吧?我可以尝试将会话ID绑定到特定IP,以便sid本身不能被盗用和滥用。 - jrharshath
除了强调用户在使用公共计算机时需要明确退出应用程序并在很短的时间内超时会话之外,您无法为用户提供太多保护措施。当然,您还需要禁用任何“记住我”的功能。 - Adam Crossland

2
设计和实现一个安全、强大、易于使用的登录系统实际上是相当困难的,第一次就能做到完美几乎不可能。已经有很多关于这个主题的文章 - 在这里无法详细涵盖。一个好的起点是www.owasp.org。然后与懂得安全知识的同事合作,与安全公司签约(例如www.matasano.com、veracode.com或neohapsis.com - 我曾与这三家公司合作,它们都非常出色),或在安全邮件列表上提问(如列在securityfocus.com上的Web应用程序安全列表)。请注意保留HTML标签。

1
非常困难,同意。几乎不可能考虑和解决所有的意外情况。 - Adam Crossland

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