我试图为用户登录记住我的功能。我想我已经涵盖了基础知识。
如果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 |
+------------------+
答案 0 :(得分:1)
记住我的令牌不应该通过JavaScript访问,也不应该通过非安全请求传输。因此,如果是这种情况,有人可以访问令牌,如果他有权访问您的数据库那么这就是另一个问题。
因此,要仅通过HTTPS请求传输cookie并将其隐藏为通过JavaScript访问,您应该在代码中替换此行
setcookie('remember', $value, $expire, '/', $_SERVER['SERVER_NAME'], true);
这一个:
setcookie('remember', $value, $expire, '/', $_SERVER['SERVER_NAME'], true, true);
有关详细信息,请阅读手册setcookie