【发布时间】:2018-02-15 12:12:15
【问题描述】:
我正在尝试为用户登录创建一个记住我的功能。我想我已经涵盖了基础知识。
如果由于某种原因 auth_tokens 表应该被泄露,则通过使 cookie 值不等于表值 (base64_encode/base64_decode) 来防止模拟。 (它们可以被解码和使用,但窃取帐户至少需要更多的工作)
cookie 中不存储任何用户信息。
当用户使用记住我 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 |
+------------------+
【问题讨论】:
-
您可以通过将 IP 添加到您的令牌并结合用户名来添加额外的安全性。您还可以保存用户登录的 IP,以便检查 IP 和令牌是否匹配。
-
是的,但是用户必须在每次更改 ip 时登录。我认为这违背了自动登录的目的。大多数人都有动态 ip。