【问题标题】:How to allow only one user edit the form in php?如何只允许一个用户在 php 中编辑表单?
【发布时间】:2020-08-07 11:50:16
【问题描述】:

我有一个如下所示的 php 代码,其中 用户名/密码 通过 db 验证,只允许一个用户登录(在下面 php 代码中的第 X 行)强>。

在 php 代码中,表 trace_usersuser_nameopenwrite 是列)保持登录用户的轨迹。当任何用户登录时,open 列设置为 true,write 列的值为 1。如果用户注销,则 open 列设置为 false,write 列的值为 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 应该被授予完全访问权限,即

用户A(open=true , write=0)

用户B(open=true, write=1)

注意:对于没有写入权限的用户,将不会显示保存按钮。

【问题讨论】:

  • 我可能理解错了,但是按照你的说法,应该只是 UserA: open = true, write = false and UserB open = true, write = false?我错过了什么吗?
  • 如果用户 A 已登录 (open=true, write=1) 并且用户 B 接管,则用户 B 应该是 open=true, write=1。接管用户 A 将是 (open=true, write=0)
  • 我同意,那有什么问题呢?你想要 php 代码来执行更改吗?看来您已经知道该怎么做了,也许我理解错了?
  • 我尝试了一些东西,但我不确定它是对还是错。如果用户 B 接管,则应为用户 A 授予只读访问权限。用户 A => open = true,write = 0 和 User B => open = true,write = 1。
  • 我的 php 代码在打开的列中只允许一个真值(一次只能登录一个)。

标签: php sql forms


【解决方案1】:

我发现您的方法存在两个基本问题:

  • 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”可能在他们的浏览器中加载了旧数据。但这是一个你没有要求解决的问题,所以无论如何它可能对你来说不是问题。

【讨论】:

    【解决方案2】:

    这样的事情怎么样?

    $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();
    

    这将撤销所有用户的写访问权限,然后仅为最近的用户设置写访问权限以请求写访问权限。

    并且您需要确保您的客户端已更新有关其撤销写入权限的信息,以便在必要时可以隐藏保存按钮。

    【讨论】:

    • 抱歉回复延迟。我想知道这段代码会去哪里?它会在 if 块内回显"&lt;script type='text/javascript'&gt;if(confirm('$message')) { } else { };&lt;/script&gt;"; 吗?
    • 我想知道您是否可以让我知道如何将 sql 查询集成到 if 块的花括号中。
    【解决方案3】:

    不建议在大型数据集上使用,但单行选项是将更新替换为包含对用户名的引用的更新:

    $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']);
    

    这将对表中的每条记录:

    • 在 1 处保留 open=1
    • 在用户名为 targetUser 的情况下设置 open=1
    • 保持 open=0,其中 is 为 0,用户名不是 targetUser
    • 在用户名为 targetUser 的情况下设置 write=1
    • 在用户名不是 targetUser 的情况下设置 write=0

    一击即中。


    对于大型数据集,创建单独的表进行跟踪。您可以使用唯一键或主键执行其他智能操作,以确保仅更新一条记录,然后验证“如果记录已更新(即rowCount() &gt; 0),那么我得到了标志,如果没有,其他人得到了它”。仅当您更习惯 MySQL 时才考虑这一点。


    警告:“Open”和“Write”都是关键字/保留字,您的 SQL 可能不可移植。要么用反引号换行,要么以 userOpen、userWrite 之类的开头。我在下面的示例中添加了反引号。在这里阅读更多:https://dev.mysql.com/doc/refman/8.0/en/keywords.html

    $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']);
    

    【讨论】:

      【解决方案4】:

      问题更多在于流程逻辑,而不是代码:

      1. UserA 连接(调用 1,php 授予访问权限:打开 => 1,写入 => 1)
      2. UserB 连接(调用 2,php 向 UserB 显示弹出窗口:open => 1)
      3. UserB 必须决定接管(或不接管)(调用 3,php 授予 UserB 写入权限并撤销 UserA 的写入权限:UserA write => 0, UserB write=>1)

      使用您的代码管理第 1 步和第 2 步。 当 UserB 决定接管时,步骤 2 的 php 代码已经结束(您提示了问题)。您必须编写专门的代码来获得 UserB 对问题的回答(这完全取决于您准备的 javascript)。

      无论如何,您没有检查任何写访问权限,因此一旦用户 B 接管然后注销,用户 A 仍将处于打开连接状态但没有写访问权限。如果 UserB 再次连接,它将再次提示接管不存在的内容(UserA 写入权限已消失)。

      【讨论】:

      • 抱歉耽搁了。在你的Point 2中,你提到了open => 1。除非用户未登录,否则不会设置为 1。就是这样,我已经设计了流程。
      • 没关系,无论第 2 步的打开状态是什么,即使他没有尝试连接。 (并且选择是接管或不连接)。没关系,他决定接管与否是在第 2 步和第 3 步之间。所以第 3 步负责这个选择。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-18
      • 2013-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多