PHP记得我的饼干

时间:2018-02-15 12:12:16

标签: php cookies

我试图为用户登录记住我的功能。我想我已经涵盖了基础知识。

如果auth_tokens表由于某种原因而被泄露,则通过不使cookie值等于表值(base64_encode / base64_decode)来防止模拟。 (它们可以被解码和使用,但至少还需要更多的工作来窃取帐户)

Cookie中不存储任何用户信息。

当用户使用remember me cookie成功登录时,会设置会话以防止数据库获得无用的请求。

每次登录时都会设置新的选择器,令牌和过期日期

所以现在我的问题是,有没有办法阻止某人窃取cookie值,然后创建记住我的cookie以成功登录该用户?

这是我使用会话安全的方式,还是有人可以将这些内容设置为他们想要的价值?

我的最后一个问题。是否应该对AUTH_TOKENS表中的USER_ID进行编码,以便更难猜测令牌属于哪个用户?如果是这样,我将如何在需要时从用户表中选择正确的用户ID。

if(auto login) {

    $expire = time() + 3600 * 24 * 30; // Cookie expire time
    $expire_encoded = base64_encode($expire); // Expire encoded

    $token_encoded = base64_encode(bin2hex(random_bytes(32))); // 32chars token encoded
    $token = base64_decode($token_encoded); // 32 chars token decoded

    $selector_encoded = base64_encode(bin2hex(random_bytes(16))); // 16 chars token encoded
    $selector = base64_decode($selector_encoded); // 16 chars token decoded

    $userid = 1; // User id
    $value = "$selector|$token"; // Cookie value

    setcookie('remember', $value, $expire, '/', $_SERVER['SERVER_NAME'], true); // Set cookie

    // Insert to db (not an actual function, just for this post. I'm using bind parm)
    insert_db(SELECTOR = $selector_encoded, USER_ID = $userid, TOKEN = $token_encoded, EXPIRES = $expire_encoded, IP = ip, date = date/time)

}

if((isset($_COOKIE['remember']) && (!isset($_SESSION['logged_in']))) {

    $tokens = explode('|',$_COOKIE['remember']);

    $selector = base64_encode($tokens[0]);
    $token = base64_encode($tokens[1]);

    // Select from db (not an actual function, just for this post. I'm using bind parm)
    $row = select_from_db(WHERE SELECTOR = $selector AND TOKEN = $token);

    if(mysqli_num_rows($row) === 1){

       // User logged in
       $_SESSION['logged_in'] = true;
       $_SESSION['user_id'] = $row['USER_ID'];

       // Generate new selector, token and expire date and insert to db

    } else {

      // User not logged in

    }

}

我的auth_tokens表看起来像这样

    +------------------+
    | AUTH_TOKENS      |
    +------------------+
    | ID               |
    | SELECTOR         |
    | USER_ID          |
    | TOKEN            |
    | EXPIRES          |
    | IP               |
    | DATE             |
    +------------------+

1 个答案:

答案 0 :(得分:1)

记住我的令牌不应该通过JavaScript访问,也不应该通过非安全请求传输。因此,如果是这种情况,有人可以访问令牌,如果他有权访问您的数据库那么这就是另一个问题。

因此,要仅通过HTTPS请求传输cookie并将其隐藏为通过JavaScript访问,您应该在代码中替换此行

setcookie('remember', $value, $expire, '/', $_SERVER['SERVER_NAME'], true);

这一个:

setcookie('remember', $value, $expire, '/', $_SERVER['SERVER_NAME'], true, true);

有关详细信息,请阅读手册setcookie