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

如何在php中只允许一个用户编辑表单?,php,sql,forms,Php,Sql,Forms,我有一个php代码,如下所示,用户名/密码通过db进行验证,只允许一个用户登录(在下面php代码的第X行) 在php代码中,表跟踪用户(用户名,打开,写入是列)跟踪登录用户。当任何用户登录时,open列被设置为true,并且write列上的值为1。如果用户注销,则列open设置为false,在write列上设置值0 登录用户=>open=true,write=1 当用户注销时=>open=false,write=0 php代码: if ($user_from_db && pass

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

在php代码中,表跟踪用户(用户名打开写入是列)跟踪登录用户。当任何用户登录时,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";
}
问题陈述:

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";
}
我想知道我应该在上面的php代码中做些什么更改,以便如果userA已登录并且userB也想登录并尝试接管表单 然后,userA应该没有写访问权限,userB应该被授予完全访问权限,即

userA
(open=true,write=0)

userB
(open=true,write=1)


注意:对于无写访问,用户不会显示保存按钮

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

  • 对于多个用户,
    trace\u users.write
    列可能会无意中设置为
    1
    ,除非您在更新表之前非常小心地锁定了它。这不是追踪谁是“活跃”编辑的好方法

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

像这样的事情怎么样

$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();
这将撤消所有用户的写访问权限,然后仅为最近请求写访问权限的用户设置写访问权限


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

不建议在大型数据集上使用此按钮,但您可以使用包含用户名引用的更新替换您的更新:

$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,其中为1
  • 设置open=1,其中username为targetUser
  • 保持打开=0,其中为0,用户名不是targetUser
  • 设置write=1,其中username为targetUser
  • 设置write=0,其中用户名不是targetUser
一炮打响


对于大型数据集,创建一个单独的表进行跟踪。您还可以使用唯一键或主键执行其他智能操作,以确保只有一条记录得到更新,然后验证“如果记录得到更新(即
rowCount()>0
),则我得到了标志,如果没有,则其他人得到了标志”。只有在你更习惯于使用MySQL时才考虑。
警告:“打开”和“写入”都是关键字/保留字,您的SQL可能无法移植。要么在后面加上记号,要么在前面加上类似userOpen、userWrite之类的东西。我在下面的示例中添加了回勾。请在此处阅读更多信息:


问题更多地出现在流程逻辑中,而不是代码中:

  • UserA连接(调用1,php授予访问权:open=>1,write=>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有关)


    不管怎样,您并没有检查任何写访问权限,所以一旦UserB接管并注销,UserA仍将具有打开的连接,但没有写访问权限。如果UserB再次连接,它将再次被提示接管不存在的内容(UserA写访问权限消失)。

    我可能误解了,但根据您的说法,它应该是UserA:open=true、write=false和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,用户B=>open=true,write=1。我的php代码在open列中只允许一个true值(一次只允许一个登录)。很抱歉回复延迟。我想知道这个代码会去哪里?它会在这里回显
    “if(confirm('$message'){}else{};”在if块中?我想知道您是否可以让我知道如何将sql查询集成到if的花括号中
    
    $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']);