什么是在PHP中进行用户身份验证的最佳方式?

时间:2010-02-01 19:42:01

标签: php login authentication

我一直在写2个cookie,1个包含用户ID,第2个包含密码的SH1哈希的1/2(盐渍)。它的工作方式是不言而喻的。

我意识到我并没有以最安全的方式做到这一点。这是一个更好的方法吗?最好使用单一身份验证cookie。

另外,有没有必要使用“难以计算哈希”?我的意思是,使用bcrypt,或者用漩涡对每个项目进行散列10,000次,使其成为(相对)慢的散列函数(200 ms vs小于1 ms只是简单的SHA1)?我的意思是,如果有人违反了您的数据库并获得了哈希值......那么还有什么需要保护,因为您的所有数据都在同一个数据库中(除非您有某种分散设置,我不这样做。) / p>

6 个答案:

答案 0 :(得分:20)

使用Sessions。将会话ID存储在cookie中,并将用户的状态存储在服务器端(loggedIn,userId,IP)。

阐明您需要存储在会话数组中的内容:

  • loggedIn:有关用户是否已登录的布尔变量。您可以为多个会话重复使用相同的Cookie,以便在下次访问您的网站时记住用户的用户名等。
  • userId:数据库中用户的uniqe id。使用此选项可获取有关用户的更多信息,例如用户名,电子邮件等。用户注销后,也可以将其保存在会话数组中。
  • IP:为防止有人窃取会话ID并使用它,您也会存储用户的IP。这是可选的,因为有时您希望允许用户漫游(例如,stackoverflow允许我使用笔记本电脑移动而不会在IP更改时将我退出)。
  • lastPing:上次看到用户的时间戳。这可以用来代替cookie的到期日期。如果您还存储会话的生存期,则可以由于不活动而将用户注销。这意味着会话ID cookie可以存储在用户计算机上很长一段时间。

当用户退出或因不活动而退出时,您只需将loggedIn设置为false即可。当用户使用正确的用户名和密码登录时,您将loggedIn设置为true并更新其他字段(userId,IP,生命周期)。当用户加载页面时,您会根据当前时间和lastPing检查lifetime,并更新lastPing或注销用户。

会话数据可以存储在文件系统中,也可以存储在数据库中。如果存储在数据库中,则userId是用户记录的外键,或者所有数据都可以放在用户记录中。

散列

多次重复一个值并不是一个好主意,因为你reduce the security。而是使用salt,将静态salt(例如页面名称)与用户的用户名以及密码组合在一起。花费很长时间的哈希并不比快速哈希更好,导致大摘要的哈希比导致短摘要的哈希(由于暴力)更好。对于普通站点(IE,不是银行或秘密军事组织),使用SHA1应该足够好。

答案 1 :(得分:4)

目前,识别用户的唯一标记是其用户名+盐渍密码哈希值的1/2。此令牌是静态的,这意味着它将在每个请求上保持不变,直到用户更改其密码。这意味着如果我想冒充系统中的用户,我只需要捕获/拦截一次令牌。 (除非您在创建存储在cookie中的哈希期间将熵引入令牌)。由于大多数用户很少更改密码,因此攻击者将拥有相当于非过期令牌的权限来访问用户帐户。

更好的解决方案是使用PHP的会话机制并在每个请求上调用session_regenerate_id以不断更新令牌。这样做会使会话劫持几乎不可能,特别是在具有IP地址/范围限制的SSL连接上。

  

目前我进行了0次DB调用(除了   在登录期间,或什么时候   已登录用户的更改)。我想了   它保持这种方式...... - 叶戈尔7   分钟前

默认情况下,PHP会话数据存储在文件系统中,因此您不会使用内置会话机制进行额外的数据库调用。

  

此外,是否有必要使用“硬   计算哈希“?我的意思是,   使用bcrypt或散列每个项目   用惠而浦10000次制作   它是一个(相对)慢的哈希函数   (200毫秒vs不到1毫秒只是平原   SHA1)?

将字符串散列10,000次使其比散列一次更安全10,000倍。使用SHA1或Whirlpool等单向加密进行哈希处理。

  

我的意思是,如果有人违反了你的数据库并获得了哈希......那里有什么   留下来保护,因为你的所有数据   是在同一个数据库中(除非你有   某种分散设置,   我不这样做。

Salting密码哈希保护它们不受rainbow table attacks的影响。目前,用彩虹表破解盐渍密码即使不是不可能,也是非常困难的。

答案 2 :(得分:1)

如果您想为您的网站实施“记住我”功能,可以将用户ID存储在Cookie中。

您不应将密码存储在用户的cookie中。如果他们愿意,可以将其保存在浏览器中。

答案 3 :(得分:1)

问问自己,您的安全要求有多严格,以确定这有多难。我使用Zend_Auth& Zend_Acl在我的php应用程序中处理身份验证/授权。如果您当前正在使用框架,则可以搜索它以获取建议的最佳实践。即使您没有使用框架,也可以搜索其他网站/应用程序以获得它。除了使用https登录/整个& amp;整个登录的会话,仅限http的cookie等。

答案 4 :(得分:1)

有几种方法可以做到这一点。我不会深入研究这个主题的文献。

  • 首先,最好使用SHA256之类的东西来减少碰撞的可能性。
  • 您还应该使用盐腌或双盐腌与一种可变盐(例如IP - 以防止偷窃会话)。在进行哈希处理之前,cookie字符串看起来像YOURSALT123.123.123.123USERNAMEPASSWORD
  • 将会话与您自己的Cookie结合使用。
  • 根据您的安全要求,使用SSL。

这完全取决于您需要的安全性。与银行网站相比,关于lolcats的社区网站有不同的安全要求。

答案 5 :(得分:-1)

这是最好的方式和最简单的方法

步骤1 在您的登录/索引页面输入此代码

<?php if(check if username and password is correct)
{
header('location:home.php');
$_SESSION['logged']=true;
}
else
{
header('location:index.php');
}
?>

您想要进行身份验证的页面中的第2步

<?php 
if(isset($_SESSION['logged']))
{
?>

your page content here

<?php    }
else
{
header('location:index.php');
?>

logoutpage中的第3步

<?php

session_start();
session_destroy();
header('Location:index.php');

?>

那就是