当用户登录或注册时,我会存储一个会话和cookie,并在数据库中插入一些详细信息。
login / register.php
$_SESSION['userid'] = $userid;
$selector = base64_encode(random_bytes(9));
$authenticator = random_bytes(33);
$token = hash('sha256', $authenticator);
$expires = date('Y-m-d\TH:i:s', time() + 864000);
$stmt2 = $pdo->prepare("INSERT INTO auth_tokens
(selector,token,userid,expires) VALUES (:selector, :token, :userid,
:expires)");
$stmt2->bindParam(':selector', $selector);
$stmt2->bindParam(':token', $token);
$stmt2->bindParam(':userid', $userid);
$stmt2->bindParam(':expires', $expires);
$stmt2->execute();
setcookie(
'remember',
$selector.':'.base64_encode($authenticator),
time()+(86400 * 90),
'/',
false
);
现在,当用户单击注销时,我破坏了会话和cookie
logout.php
session_start();
$_SESSION = array();
unset($_SESSION);
if (isset($_COOKIE['remember'])) {
unset($_COOKIE['remember']);
setcookie('remember', '', time() - 3600, '/'); // empty value and old
timestamp
}
session_destroy();
作为管理员,我想从自己的终端删除用户时删除用户会话和cookie。
现在,当我使用此方法在数据库中删除用户时
deleteuser.php
$stmt = $pdo->prepare("DELETE FROM users WHERE id=:uid");
$stmt->bindValue(':uid', $uid);
$stmt->execute();
if($stmt){
$stmt2 = $pdo->prepare("DELETE FROM auth_tokens WHERE userid=:uid");
$stmt2->bindValue(':uid', $uid);
$stmt2->execute();
}
当同一用户重新访问页面(index.php)时,我在页面顶部收到此错误
警告:hash_equals():期望known_string为字符串,在第17行的C:\ xampp \ htdocs \ book \ php \ function.php中给出空值
index.php
include('php/function.php');
getcookie();
function.php
if (!empty($_COOKIE['remember'])) {
list($selector, $authenticator) = explode(':', $_COOKIE['remember']);
$stmt = $pdo->prepare("SELECT * FROM auth_tokens WHERE selector=:selector");
$stmt->bindValue(':selector', $selector);
$stmt->execute();
$row = $stmt->fetch();
if (hash_equals($row['token'], hash('sha256',
base64_decode($authenticator)))) {
.....
}
}
function getcookie (){
if (!empty($_COOKIE['remember'])) {
list($selector, $authenticator) = explode(':', $_COOKIE['remember']);
$stmt = $pdo->prepare("SELECT * FROM auth_tokens WHERE
selector=:selector");
$stmt->bindValue(':selector', $selector);
$stmt->execute();
$row = $stmt->fetch();
$toke = $row['token'];
$auth = hash('sha256', base64_decode($authenticator));
if (hash_equals($row['token'], hash('sha256',
base64_decode($authenticator)))) {
$userid = $row['userid'];
// Then regenerate login token as above
}
}
}
如何调整这些代码,以便可以通过结束用户会话和cookie来有效地从我的网站中删除用户。
答案 0 :(得分:1)
您不能删除用户一方的会话/ Cookie ...但是您可以立即删除他们执行管理事务的能力。
如果在执行任何管理员级别的操作之前在服务器上基于用户的sessionID或其他方式重新检查了用户的凭据,则将有效禁用其管理员状态-然后将其转移到非管理员屏幕同时。
您可能会问:当我对他们进行核对时,如果他们具有管理员屏幕并处于活动状态怎么办?对于静态屏幕,您几乎无能为力(他们可以截取屏幕截图-您无法阻止它)。他们可以点击后退按钮,甚至可以从缓存中查看屏幕。但是
一些可能的解决方案是:
(a)每隔X秒/分钟将ajax与setInterval(或递归setTimeout)函数一起使用,以与服务器重新检查其管理凭据。然后,即使它们是afk,也可以从管理屏幕中注销。 (当然,精明的用户可以通过在DevTools中浏览来暂停此方法。)
(b)在执行任何管理员操作之前,都要重新检查其信誉。如果他们不再是管理员,则该操作将被拒绝,并返回到非管理员屏幕。精明的用户不会干扰此方法。
这不会给所有内容带来明显的延迟吗?
不。重新检查凭据就像在数据库中实时检查其用户权限状态一样简单。
当您取消管理它们时,您将更改它们的priv级别,因此,只要用户尝试从该管理屏幕执行某项操作,此权限级别就会立即被获取。除非您有数千名用户,否则不要担心这样做的开销。即使有数千名用户,它仍然可能是处理此问题的一种不错的方式。无论如何,您此时都在与服务器进行通信,并且在每个admin-action功能内,只需插入一个快速检查以“验证管理员状态”-因此,它只是服务器上与其自身数据库进行通信的后端代码。超级快。