PHP登录系统:Remember Me(持久cookie) [英] PHP login system: Remember Me (persistent cookie)

查看:35
本文介绍了PHP登录系统:Remember Me(持久cookie)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在登录前添加记住我"复选框选项.

I'd like to add a "remember me" checkbox option before logging in.

在用户浏览器中安全存储 cookie 的最佳方法是什么?

What is the best way to securely store a cookie in the user's browser?

例如,Facebook 有他们的记住我"复选框,以便您每次进入 facebook.com 时都已登录.

For example, Facebook have their "remember me" checkbox so that every time you enter facebook.com you are already logged in.

我当前的登录使用简单会话.

My current login uses simple sessions.

推荐答案

更新 (2017-08-13):了解我们为什么要将 selectortoken 分开,而不是仅仅使用 <代码>token,请阅读这篇关于拆分令牌以防止对 SELECT 查询进行计时攻击的文章.

Update (2017-08-13): To understand why we're separating selector and token, instead of just using a token, please read this article about splitting tokens to prevent timing attacks on SELECT queries.

我将提取这篇博文中概述的策略 ​​关于安全的长期身份验证,因为这涵盖了很多领域,我们只对 记住我" 部分.

I'm going to extract the strategy outlined in this blog post about secure long-term authentication since that covers a lot of ground and we're only interested in the "remember me" part.

我们想要一个与用户表不同的表,看起来像这样 (MySQL):

We want a separate table from our users' table that looks like this (MySQL):

CREATE TABLE `auth_tokens` (
    `id` integer(11) not null UNSIGNED AUTO_INCREMENT,
    `selector` char(12),
    `token` char(64),
    `userid` integer(11) not null UNSIGNED,
    `expires` datetime,
    PRIMARY KEY (`id`)
);

这里重要的是 selectortoken 是单独的字段.

The important things here are that selector and token are separate fields.

如果您没有 random_bytes(),只需获取一份 random_compat.

If you don't have random_bytes(), just grab a copy of random_compat.

if ($login->success && $login->rememberMe) { // However you implement it
    $selector = base64_encode(random_bytes(9));
    $authenticator = random_bytes(33);

    setcookie(
        'remember',
         $selector.':'.base64_encode($authenticator),
         time() + 864000,
         '/',
         'yourdomain.com',
         true, // TLS-only
         true  // http-only
    );

    $database->exec(
        "INSERT INTO auth_tokens (selector, token, userid, expires) VALUES (?, ?, ?, ?)", 
        [
            $selector,
            hash('sha256', $authenticator),
            $login->userId,
            date('Y-m-dTH:i:s', time() + 864000)
        ]
    );
}

在页面加载时重新验证

if (empty($_SESSION['userid']) && !empty($_COOKIE['remember'])) {
    list($selector, $authenticator) = explode(':', $_COOKIE['remember']);

    $row = $database->selectRow(
        "SELECT * FROM auth_tokens WHERE selector = ?",
        [
            $selector
        ]
    );

    if (hash_equals($row['token'], hash('sha256', base64_decode($authenticator)))) {
        $_SESSION['userid'] = $row['userid'];
        // Then regenerate login token as above
    }
}

详情

我们使用 9 字节的随机数据(base64 编码为 12 个字符)作为我们的选择器.这提供了 72 位的密钥空间,因此提供了 236 位的抗碰撞性(生日攻击),这比我们的存储容量(integer(11) UNSIGNED)大了一个因子共 16 个.

Details

We use 9 bytes of random data (base64 encoded to 12 characters) for our selector. This provides 72 bits of keyspace and therefore 236 bits of collision resistance (birthday attacks), which is larger than our storage capacity (integer(11) UNSIGNED) by a factor of 16.

我们使用 33 个字节(264 位)的随机数作为我们实际的验证器.这在所有实际场景中都应该是不可预测的.

We use 33 bytes (264 bits) of randomness for our actual authenticator. This should be unpredictable in all practical scenarios.

我们将身份验证器的 SHA256 哈希值存储在数据库中.这降低了信息泄露后用户冒充的风险.

We store an SHA256 hash of the authenticator in the database. This mitigates the risk of user impersonation following information leaks.

我们重新计算存储在用户 cookie 中的验证器值的 SHA256 哈希值,然后使用 <将其与存储的 SHA256 哈希值进行比较code>hash_equals() 防止定时攻击.

We re-calculate the SHA256 hash of the authenticator value stored in the user's cookie then compare it with the stored SHA256 hash using hash_equals() to prevent timing attacks.

我们将选择器与验证器分开,因为数据库查找不是恒定时间的.这消除了时间泄漏对搜索的潜在影响,而不会造成严重的性能损失.

We separated the selector from the authenticator because DB lookups are not constant-time. This eliminates the potential impact of timing leaks on searches without causing a drastic performance hit.

这篇关于PHP登录系统:Remember Me(持久cookie)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆