这个登录安全吗?

4

你好,这是我第一次这样做。我已经阅读了网站身份验证的明确指南http://en.wikibooks.org/wiki/PHP_Programming/User_login_systems,但我仍然对自己是否正确地完成此操作存在疑虑。注意:我这样做是为了学习,请不要建议使用框架、php pear auth或任何其他相关类。我只想得到一些指导,以改进这个。

我不需要CIA级别的安全性,只需要一个基本的登录网站:

无论如何,这就是我的登录方式:

  1. 等待用户按下登录按钮

    if (isset($_POST['action']) && $_POST['action'] == 'Login')

  2. 表单令牌是否与会话中存储的令牌匹配?如果不匹配,则退出。

  3. 使用php过滤器验证用户名和密码中的字符串
  4. 哈希密码(sha256)(带盐,我对每个密码使用相同的盐)
  5. 使用mysqli检查用户名和哈希密码(在SQL中限制为1)。
  6. 如果没有找到匹配项,则显示错误--否则设置会话(使用sha256哈希)

在所有这些操作的底部,我放置了以下内容,这是我最担心的一行:

我的想法是,如果会话未设置,则显示登录表单并退出。

 if
 (!isset($_SESSION['authenticated'])) {
     require_once 'html/login_form.html';  
     exit();   }
 // secret stuff goes here

这里可以找到完整的代码,但它仍然是不完整的

我还尝试实现这个:如何在PHP中限制用户登录尝试次数

欢迎任何反馈意见。


1
开始一个事务。锁定行以进行更新。延迟5秒。释放事务。登录尝试被限制。 - Ignacio Vazquez-Abrams
@john:为什么你计划重复使用你的盐?你应该为每个密码使用一个唯一的盐。 - AgentConundrum
@AgentConundrum,那我是不是也要将盐值存储在数据库中?这样为了检查密码是否正确,我就必须匹配哈希(password + salt_from_db)了吗? - john mossel
@john:完全正确。像那样存储盐可能看起来不安全,但请记住:a)您无论如何都必须在某个地方存储“主盐”,b)为每个密码使用唯一的盐意味着即使您的整个数据库被攻击者入侵,攻击者也需要为数据库中的每个密码生成一个独特的彩虹表。 - AgentConundrum
2个回答

2

这是一个非常开放的问题,因为有很多方面需要挖掘。 但是,就“平均”安全而言,我至少建议更改以下内容。

第二点:不要使用相同的盐。这意味着如果盐被攻击,则所有哈希值都会被攻破。我建议单向加密密码。用户宁愿重置密码而不想知道可以被合理解密。

第五点:不要忘记SQL注入。比LIMIT 1重要得多。查看mysql_real_escape_string()


所以我应该使用filter_input和mysqli_real_escape_string。我之前使用了mysqli_real_escape_string,但我认为filter_input会处理它。谢谢。 - john mossel
看起来似乎有些冗余,但这样做可以增加安全性。如果其中一个部分存在漏洞,另一个部分仍然可以提供保护。 - Jason McCreary

1

首先,没有什么是100%安全的。为了使您的登录更加安全,您可以添加以下一些内容:

  1. 挑战响应 - http://en.wikipedia.org/wiki/Challenge-response_authentication
  2. 三次握手协议 - http://en.wikipedia.org/wiki/Three-pass_protocol
  3. 哈希组合用户名和密码 md5(password + salt + username)
  4. 使用JavaScript在客户端进行验证,然后再在服务器上进行验证
  5. 使用数据库抽象库来防止SQL注入。

还有很多其他方法,但这取决于您需要多么安全以及您想让用户经历多少麻烦。根据您的应用程序需要找到某种平衡。

我的经纪账户在进入登录页面之前会使用图片和挑战。这很麻烦(经纪账户需要),但在博客上可能不会那么麻烦。


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