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


Designing a secure auto login cookie system in PHP

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

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

我的一个朋友建议有一个db表,存储session_id,用户的ip,浏览器信息等,然后比较它所有的信息,一旦用户再次去网站。

我想要一张单独的桌子,因为那太麻烦了。还有别的办法吗?也许是代币之类的?

你越希望这个臭名昭著的cookie安全,它给你带来的麻烦就越多。如果你的用户需要特别的安全,你将不得不采用最麻烦的方法。

如果你想要尽可能的安全,你应该只接受https的cookie。如果cookie通过http被接受,它可以被嗅探和窃取。

我建议cookie中不包含任何用户数据(如您所建议的,使用令牌)。不幸的是,这将需要另一张表。当用户登录并选择"保持登录"时,在该表中创建一个条目。该表项可以是任何无意义的值(如md5(uniqid('', true));)。这个令牌在DB中可以是唯一的,并映射到用户的ID。

当用户访问您的网站时,您可以检查该cookie的值,并获得它所属的用户并登录他们。此时,您将销毁旧令牌并创建一个新令牌。"Destroy"有很多意思。您可以将其从DB中完全删除,或者使用禁用令牌的标志。您可能希望允许多次使用相同的令牌,以防cookie被接收,但由于某种原因身份验证没有通过,但我认为这是不安全的。您可能还希望存储令牌的时间戳,并且仅在某个有限的时间段内(例如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;
}

在登录时将此值分配给用户cookie。然后将其存储到db:

function save_ident($identFromFunctionAbove,$authenticated_user_id){
    //hash this with something unique to the user's machine
    $hashed = md5($identFromFunctionAbove . $_SERVER['REMOTE_ADDR']);
    /** Some actions to remember this hash **/
}

将其保存到与用户标识(如user_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或标识冲突。但是,让两个32个字符随机生成的字符串与之前生成的字符串相同的可能性非常小。

我之前的方法是存储密码的MD5哈希值,而不是实际密码。

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

这样,如果有人入侵了用户的计算机,他们永远也不会知道密码的值,但是他们仍然可以使用cookie来验证你的服务器。

你可以通过设置cookie在x天后过期来使其更安全,这样如果cookie被盗,窃贼只能在这段时间内访问。

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