所以我刚刚构建/黑客攻击了我的第一个cookie验证公式,似乎工作正常,但已经意识到它不适应用户登录多个设备时,以及一个测试报告缓慢(我不能直接证明饼干)。我确实认识到解决多个设备问题的一些可能方法,但由于我以前从未真正使用过cookie,所以我想就最佳方式来处理这个问题。如果有人对我的方法有任何其他建议,他们将不胜感激,我几乎肯定会在添加每个页面的标题之前实现它们。
function rememberMe() {
$cookie = isset($_COOKIE['rememberme']) ? $_COOKIE['rememberme'] : '';
if ($cookie) {
list ($username, $token, $mac) = explode(':', $cookie);
if ($mac !== hash_hmac('sha256', $username . ':' . $token, XXXX)) {
return false;
}
function fetchTokenByUsername($username) {
$host="";
$dbusername="xxxx";
$dbpassword="xxxx";
$database="xxxx";
global $mysqli;
$stmt = $mysqli->prepare("SELECT username, token
FROM cookielogin
WHERE username=? //pull most recent cookie key from DB
ORDER BY keyid DESC
LIMIT 1");
$stmt->bind_param('s', $username);
if (!$stmt) {
header('Location: login.php');
die();
}
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($userjunk, $userToken);
$stmt->fetch();
return $userToken;
}
function logUserIn($username) {
$host="";
$dbusername="xxxx";
$dbpassword="xxxx";
$database="xxxx";
global $mysqli;
$active=1;
$stmt = $mysqli->prepare("SELECT id, email, username, password, gender, homelat, homelng, salt FROM users WHERE username=? AND active=?");
$stmt->bind_param('si', $username, $active);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($id, $email, $xusername, $xpassword, $gender, $homelat, $homelng, $salt);
$stmt->fetch();
if (!$stmt) {
header('Location: login.php');
die();
}
$numrows = $stmt->num_rows;
if ($numrows == 0) {
$_SESSION['loggedin'] = false;
$_SESSION['error'] = ("Incorrect username and password combination, please try to log in again");
exit();
}
session_regenerate_id(); // set session information
$_SESSION['sess_user_id'] = $id;
$_SESSION['sess_email'] = $email;
$_SESSION['sess_username'] = $xusername;
$_SESSION['sess_gender'] = $gender;
$_SESSION['sess_homelat'] = $homelat;
$_SESSION['sess_homelng'] = $homelng;
$_SESSION['loggedin'] = true;
}
function timingSafeCompare($userToken, $token) {
//removed for brevity (and pulled from a library, so I am confident in it's abilities)
}
$userToken = fetchTokenByUsername($username);
if (timingSafeCompare($userToken, $token) === 0) {
logUserIn($username);
return true;
}
}
else{
return false;
}
}
if ((isset($_SESSION['sess_username']) and $_SESSION['sess_username'] != '') ||(rememberMe()== true)):
如您所见,我只根据我数据库中最近存储的cookie密钥检查用户cookie。这是多个设备存在问题的地方。我虽然可以从数据库中提取最后5个cookie密钥,然后构建一个数组,然后检查它们是否在数组中。尽管如此,这似乎并不是万无一失的证明。我还想我可以用ip地址保存每个cookie,但这显然会在VPN下失败。 至于现在,我只存储cookie密钥,其中包含用户名,上次使用时间和自动增量列。
真诚地感谢您的帮助。非常感谢。
答案 0 :(得分:0)
您可以在您的select语句中添加Cookie的标记作为条件:
<?php
$stmt = $mysqli->prepare("SELECT username, token
FROM cookielogin
WHERE username=? //pull most recent cookie key from DB
AND token=?
ORDER BY keyid DESC
LIMIT 1");
$stmt->bind_param('ss', $username, $token);
允许您为每个设备使用不同的Cookie。