我有一个如下所示的php代码,其中通过数据库验证了用户名/密码,并且仅允许一个用户登录(在下面php代码的X行)。
在php代码中,表 trace_users (用户名,打开,写入是列)保留登录用户的轨迹。当任何用户登录后,写入列上的打开列将设置为true,值为 1 。如果用户注销,则在写入列上将打开列设置为false,将其值设置为 0 。
已登录用户 => open = true, write = 1
用户注销时 => open = false, write = 0
php代码:
if ($user_from_db && password_verify($password, $user_from_db->user_pass)) {
$sql = "SELECT * FROM trace_users where open='true'";
if($result1 = mysqli_query($connect, $sql)){
if(mysqli_num_rows($result1) > 0){ // Line X
while($row = mysqli_fetch_array($result1)){
if($row['open'] == "true") {
if(!isset($_SESSION['admin'])) {
$message = "user " . $row['user_name'] . " is currently editing the form. Want to take over ?";
echo "<script type='text/javascript'>if(confirm('$message')) { } else { };</script>"; // Line A
}
break;
}
}
} else{
$_SESSION['admin'] = true;
$_SESSION['user_name'] = $username;
$open="true";
$write="1";
$stmt= $connect->prepare("UPDATE trace_users SET open=?, write=? WHERE user_name=?");
$stmt->bind_param('sss', $open, $write, $_SESSION['user_name']);
$stmt->execute();
}
}
} else {
echo "Invalid Username or Password";
}
在A行中,如果 userA 已登录,而另一个用户说 userB 尝试登录,则它将显示userA is currently editing the form. Want to take over ?
。
我要实现的是如果 userB 接管了在警报框中单击“确定” 的形式,那么 userA 应该进入只读模式(撤消)写访问权限)和 userB
被授予完全访问权限(写)。
userA => open = true, write = 0
userB => open = true, write = 1
这是我尝试过的:
在A行之后,我正在考虑添加这些行,以便尝试接管的用户能够登录。
$_SESSION['admin'] = true;
$_SESSION['user_name'] = $username;
$open="true";
$write="1";
$stmt= $connect->prepare("UPDATE trace_users SET open=?, write=? WHERE user_name=?");
$stmt->bind_param('sss', $open, $write, $_SESSION['user_name']);
$stmt->execute();
问题陈述:
我想知道我应该在上面的php代码中进行哪些更改,以便如果 userA 登录并且 userB也希望登录并尝试接管表单 那么 userA 应该没有写访问权限,而 userB 应该具有完全访问权限,即
userA (open=true , write=0)
userB (open=true, write=1)
注意:对于没有写访问权限的用户,将不会显示保存按钮。
答案 0 :(得分:0)
我发现您的方法存在两个基本问题:
可能会无意中将多个用户的trace_users.write
列设置为1
,除非您在更新表之前非常小心地锁定了表。这不是跟踪谁是“活动”编辑器的好方法。
您的line "A"
可能会显示一些HTML,但是直到用户确认是/否,它才会被执行。该步骤必须在其他地方完成。
一种更好的方法是让一条规范记录(可能在另一个表中)跟踪当前管理员,并且您的代码可以根据需要随时检查(或更新)该记录。每当用户选择进行更改时,PHP都会首先检查他们是否是活动的编辑器,如果是,则提交更新,否则拒绝更新。
您需要的一些服务器端功能的伪代码:
// When an update is requested:
if ( user is logged in and is the current admin ) {
commit the change;
} else {
Display "sorry" message to user
}
// -----------
// When user "X" logs in:
if ( another user is currently the active admin ) {
Display message: "User Y is currently the admin. Take over?"
} else {
Log in user "X" and set user "X" to current admin
}
// -----------
// When user "X" asks to take over as admin:
log in user "X"
set user "X" to current admin
我在这里看到的唯一缺陷是用户“ A”已登录并编辑并保存更改,用户“ B”可能在其浏览器中加载了旧数据。但这不是您要解决的问题,因此无论如何对您来说都不是问题。
答案 1 :(得分:0)
这样的事情怎么样?
$username = $_SESSION['user_name'];
$open="true";
$write="1";
$stmt=$connect->prepare("UPDATE trace_users SET write=0 WHERE write=1"); // revoke write access of all users
$stmt=$connect->prepare("UPDATE trace_users SET open=:open, write=:write WHERE user_name=:username");
$stmt->bind_param('sss', $open, $write, $username);
$stmt->execute();
这将撤消所有用户的写访问权限,然后仅为最近的用户设置写访问权限以请求写访问权限。
并且您将需要确保客户端有关其写访问权的撤销的最新信息,以便在必要时可以隐藏保存按钮。
答案 2 :(得分:0)
不建议在大型数据集上使用,但您可以使用一行选项来替换为包含对用户名的引用的更新:
model.fit()
这将针对表中的每个记录:
一键通。
对于大型数据集,创建一个单独的表进行跟踪。您还可以使用其他智能功能,使用唯一键或主键来确保仅更新一条记录,然后验证“如果记录已更新(即$stmt= $connect->prepare("UPDATE trace_users SET open=IF(open=1 OR user_name=?,1,0), write=IF(user_name=?,1,0)");
$stmt->bind_param('sss', $_SESSION['user_name'], $_SESSION['user_name']);
),那么我会得到该标志,如果没有,那么其他人会得到它”。仅当您更习惯MySQL时才考虑。
警告:“打开”和“写入”都是关键字/保留字,您的SQL可能无法移植。换行或在开头加上诸如userOpen,userWrite之类的内容。我在下面的示例中添加了滴答声。在此处阅读更多信息:https://dev.mysql.com/doc/refman/8.0/en/keywords.html
rowCount() > 0
答案 3 :(得分:0)
问题更多的是流程逻辑,而不是代码:
使用代码管理第1步和第2步。 当UserB决定接管时,步骤2的php代码已经结束(您的提示问题)。您必须编写专用的代码来获得UserB回答的问题(这与您准备的javascript有关)。
无论如何,您都不会检查任何写访问权限,因此,一旦UserB接管然后注销,UserA仍将保持开放连接,但没有写访问权限。如果UserB重新连接,则会再次提示您接管不存在的内容(UserA的写访问权限已消失)。