用PHP设计安全的自动登录cookie系统

用PHP设计安全的自动登录cookie系统,php,cookies,setcookie,login-script,Php,Cookies,Setcookie,Login Script,我想检查用户的自动登录选项。基本上,这意味着cookie将存储在客户端 现在的问题是,如何使其安全,使cookie不会被欺骗/修改 我的一个朋友建议使用一个db表来存储会话id、用户ip、浏览器信息等,然后在用户再次访问该网站时比较所有这些信息 我想要一张单独的桌子,因为那有点太麻烦了。还有别的办法吗?可能使用令牌或类似的东西?我以前这样做的方式是存储密码的MD5散列,而不是实际密码 在服务器端,您需要检查登录名是否来自cookie,然后检查哈希值是否与数据库中通过MD5哈希后的密码相同 这样,

我想检查用户的自动登录选项。基本上,这意味着cookie将存储在客户端

现在的问题是,如何使其安全,使cookie不会被欺骗/修改

我的一个朋友建议使用一个db表来存储会话id、用户ip、浏览器信息等,然后在用户再次访问该网站时比较所有这些信息


我想要一张单独的桌子,因为那有点太麻烦了。还有别的办法吗?可能使用令牌或类似的东西?

我以前这样做的方式是存储密码的MD5散列,而不是实际密码

在服务器端,您需要检查登录名是否来自cookie,然后检查哈希值是否与数据库中通过MD5哈希后的密码相同

这样,如果有人入侵用户的计算机,他们永远不会知道密码的值,但是用户仍然可以使用该cookie仅向您的服务器进行身份验证

您可以通过使cookie在x天后过期来提高安全性,因此如果cookie被盗,theif只能在该时间段内访问


在一天结束的时候,最多也是唯一的?安全的方法是让用户每次登录

你越想要这个臭名昭著的cookie,它给你带来的麻烦就越多。如果您的用户应该特别安全,您将不得不使用最麻烦的方法

如果您希望尽可能安全,您应该只接受带有https的cookie。如果cookie通过http被接受,它可以被嗅探和窃取

我建议cookie完全没有用户数据(如您所建议的,是一个令牌)。不幸的是,这需要另一张桌子。当用户登录并选择“保持登录”时,在此表中创建一个条目。条目可以是任何无意义的值(例如
md5(uniqid(“”,true));
。此标记在数据库中可以是唯一的,并映射到用户ID


当用户访问您的网站时,您可以检查该cookie的值,获取该cookie所属的用户并登录。此时,您将销毁旧令牌并创建一个新令牌。“销毁”可能意味着很多事情。您可以将其从数据库中完全删除,也可以使用一个禁用令牌的标志。如果收到cookie但由于某种原因身份验证未通过,您可能希望允许同一令牌被多次使用,但我认为这是不安全的。您可能还希望存储令牌的时间戳和ONLAMP如果时间有限(例如30天),我会接受

正如您的朋友所指出的,您可以存储其他信息,如用户代理、IP地址等,但即使使用相同的浏览器(尤其是移动设备),这些信息也可能会发生变化。如果用户的持久登录因此而不被接受,这可能会使他们感到不安和不便


如果你真的不想创建另一个表,那么你必须存储某种方法来从cookie值获取用户ID。这不太安全。

对于我所知道的大多数自动登录,都有一个单独的表来存储登录的会话。每个自动登录会话都分配了一个哈希键作为标识符,该键相当长,而且实际上不可能进行欺骗。如果您不希望用户使用有效代码跨ip登录,请尝试此操作

function gen_uniqueIdent($length=32){
    $alphabet = str_split('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789');
    $key = '';
    for($loop=0;$loop<$length;$loop++){
        $i = mt_rand(0,count($alphabet)-1);
        $key.= $alphabet[$i];
    }
    return $key;
}
将其保存到与用户标识(如用户id)对应的数据库中

现在,在验证用户cookie后,您可以简单地:

function validateCookie(){
    $ident = $_COOKIE['yourCookieName'];
    $hashed = md5($ident . $_SERVER['REMOTE_ADDR']);
    /** Check if this hashed value exists in db, if it does, authenticate user **/
}
您还需要在会话过期或用户显式注销后删除会话


当然,这很简单,不考虑md5或ident冲突。不过,让两个32字符随机生成的字符串与之前生成的字符串相同的可能性很小。

密码应该在按原样存储之前进行哈希运算。是的,他们可以使用Rainbow表崩溃密码。一旦er使用cookie登录,如果我将会话变量用于某个或更好的用途,我是否必须手动设置该变量,“会话”是如何进行的还原吗?@CodeCrack实际上,上面提到的方法是用php创建您自己的会话管理方法。因此,基本上,您必须手动设置会话变量以使用此方法的php会话。“当用户访问您的网站时,您可以检查该cookie的值,获取它所属的用户并登录”最好的方法是什么?只需将他们的用户/密码从db重定向到安全页面?@CodeCrack您可以完全控制用户是否经过身份验证,因此没有最好的方法。只需执行与他们输入用户名/密码后相同的操作。您可能已经(或可以创建)一个名为
complete\u login()的函数或东西
这是会话所需的数据。在登录时销毁旧令牌的好处是什么?我想在那一刻也会向客户端传递一个新令牌,不是吗?@Uwe只是一个额外的安全步骤——为什么要保留比需要更长时间的认证?可能还有更好的原因,但例如,如果alicious用户获得了您的令牌,而您从未销毁过它,他们可以永远以您的身份登录。您好,当用户A的cookie被复制时(由有权访问用户A计算机的人复制)并粘贴在该特定网站的任何计算机上,它最终会将用户A的所有信息显示给在本地访问该用户A计算机的人。如何防止这种情况。有想法社区吗?
function validateCookie(){
    $ident = $_COOKIE['yourCookieName'];
    $hashed = md5($ident . $_SERVER['REMOTE_ADDR']);
    /** Check if this hashed value exists in db, if it does, authenticate user **/
}