如何只允许一个用户在 php 中编辑表单?

Posted

技术标签:

【中文标题】如何只允许一个用户在 php 中编辑表单?【英文标题】:How to allow only one user edit the form in 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 代码在打开的列中只允许一个真值(一次只能登录一个)。 【参考方案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】:

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

    UserA 连接(调用 1,php 授予访问权限:打开 => 1,写入 => 1) UserB 连接(调用 2,php 向 UserB 显示弹出窗口:open => 1) 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 步负责这个选择。

以上是关于如何只允许一个用户在 php 中编辑表单?的主要内容,如果未能解决你的问题,请参考以下文章

只允许在使用 PHP 的表单中选择一个单选按钮

如何在没有表单字段的情况下从表单传递数据? (PHP)

[php内的html表单进行循环-编辑/删除按钮

PHP表单提交失败,如何返回原值?

如何为Extjs的form表单组件里面的每一个字段增加一个编辑按钮

如何使用 iTextSharp 正确填写 XFA 表单数据以允许在 Acrobat XI 中编辑和保存结果