繁体   English   中英

如何让按钮执行php脚本?

[英]How to make a button execute a php script?

如何使 html 按钮执行 php 脚本?

我正在开发一个只有一个用户可以登录的登录系统,每当其他用户尝试登录时,它应该给他们一个警告弹出消息,说another user is already logged in - Do you want to take over from them?

  • 如果userA已经登录并且userB尝试登录,那么它应该显示在弹出窗口中,因为userA is already logged in, do you want to take over? .
  • 现在对于幕后的userA ,我们将取消写入权限并向他们显示另一个弹出消息,表明您的写入权限已被撤销。

第二点我可以稍后处理,但现在我专注于做第一点。 以下是我试图在LINE A实现第一点的代码 -

if (isset($_POST['user_name'], $_POST['user_pass']) && $_POST['user_login'] == 1) {
    //Assigning posted values to variables.
    $username = $_POST['user_name'];
    $password = $_POST['user_pass'];

    //Checking the values are existing in the database or not
    $stmt = $connect->prepare("SELECT user_pass FROM userspanel WHERE user_name=?");
    $stmt->bind_param('s', $username);
    $stmt->execute();
    $result = $stmt->get_result();
    $user_from_db = $result->fetch_object();

    if ($user_from_db && password_verify($password, $user_from_db->user_pass)) {

        $_SESSION['user_name'] = $username;

        $sql = "SELECT * FROM trace_users where open='true'";
        $result1 = mysqli_query($connect, $sql);
        if($result1 = mysqli_query($connect, $sql)){
            if(mysqli_num_rows($result1) > 0){
                while($row = mysqli_fetch_array($result1)){
                    if($row['open'] == "true") {
                        if(!isset($_SESSION['pageadmin'])) {
                            $message = "user " . $row['user_name'] . " is logged in. Do you want to take over ?";
                            // LINE A
                            // how to show pop up button which shows $message on it
                            // and add action on ok and cancel button here?
                        }
                        break;
                    }
                }
            } else{
                $_SESSION['pageadmin'] = true;
                $open = "true";
                $read_access = "1";
                $write_access = "1";
                $stmt = $connect->prepare("UPDATE trace_users SET open=?, read_access=?, write_access=? WHERE user_name=?");
                $stmt->bind_param('ssss', $open, $read_access, $write_access, $username);
                $stmt->execute();
            }
        }

    } else {
        echo "Invalid username and password";
    }
}

我想完成以下任务,但我对如何实现感到困惑-

  • LINE A ,我想显示一个弹出消息,说"Previous user is logged in. Do you want to take over?" 与确定和取消按钮。
  • 一旦我点击弹出消息上的Ok按钮,然后我想在 php 中执行某些代码,假设现在打印hello world ,如果我点击弹出消息上的cancel按钮,那么我不想做任何事情。

简而言之,我想实现两件事:

1.在 A 行创建一个带有 Ok 和 Cancel 按钮的弹出消息。
2.单击“确定”按钮,我想执行 php 脚本,单击“取消”按钮,我不想发生任何事情。

基本场景:

  • 将当前已验证用户的唯一ID时间以以下格式(作为 JSON)存储在.txt文件中:
json_encode(['user_id' => 1, 'created_at' => (new DateTime('now'))->format('Y-m-d H:i:s')]);
  • 当用户尝试登录时,检查文件中存储的user_idcreated_at字段。
  • 如果文件为空,则用户登录并将用户的唯一ID和时间写入文件。
  • 如果文件不为空并且user_id字段与尝试登​​录的用户的id相同并且created_at字段不早于 12 小时前(或您的自定义逻辑),则只需更新文件中的created_at字段并登录用户在。
  • 如果文件不为空并且user_id字段与尝试登​​录但已超过 12 小时(或您的自定义逻辑)的用户的id相同,则询问用户他/她是否想接管另一个用户。
  • 如果文件不是空的, user_id一样的id谁登录尝试询问用户是否他/她想要接管其他用户的用户。

基本实现:

  1. 在您的项目目录中创建一个.txt文件。
  2. 将这些辅助函数添加到您的项目中(在我的例子中是helpers.php ):
if (! function_exists('check_auth')) {
    function check_auth(): bool
    {
        if (! isset($_SESSION['user_id'])) {
            return false;
        }

        if (! file_exists('current_user.txt') || filesize('current_user.txt') === 0) {
            return true;
        }

        $trace = json_decode(file_get_contents('current_user.txt'));

        // You can write your own logic here.
        return (int) $trace->user_id === $_SESSION['user_id'] && (new DateTime($trace->created_at))->modify('+12 hours') > new Datetime('now');
    }
}

if (! function_exists('logout'))
{
    function logout()
    {
        if (isset($_SESSION['user_id'])) {
            $trace = json_decode(file_get_contents('current_user.txt'));

            if ((int) $trace->user_id === $_SESSION['user_id']) {
                file_put_contents('current_user.txt', '');
            }

            unset($_SESSION['user_id']);
        }
    }
}

if (! function_exists('redirect')) {
    function redirect(string $url, int $status_code = 303): void
    {
        header('Location: ' . $url, true, $status_code);
        die();
    }
}
  1. 创建一个登录页面(在我的例子中是login.php ):
<?php

declare(strict_types=1);

// Start session.
session_start();

// Include helper functions.
require_once 'helpers.php';

// Redirect user to homepage/dashboard if authenticated.
if (check_auth()) {
    redirect('index.php');
    return;
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $pdo = new PDO('mysql:host=[DB_HOST];dbname=[DB_NAME];charset=utf8mb4', '[DB_USERNAME]', '[DB_PASSWORD]', [
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
        PDO::ATTR_EMULATE_PREPARES   => false,
    ]);
    $stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?');
    $stmt->execute([$_POST['email']]);
    $user = $stmt->fetch();

    if (! ($user && password_verify($_POST['password'], $user->password))) {
        echo json_encode([
            'success' => false,
            'message' => 'These credentials don\'t match our records.',
        ]);
        return;
    }

    // Log user in if another is not authenticated.
    if (filesize('current_user.txt') === 0) {
        file_put_contents('current_user.txt', json_encode([
            'user_id'    => $user->id,
            'created_at' => (new DateTime('now'))->format('Y-m-d H:i:s'),
        ]));

        $_SESSION['user_id'] = $user->id;

        echo json_encode([
            'success' => true,
        ]);

        return;
    }

    $trace = json_decode(file_get_contents('current_user.txt'));

    // Log user in if the last authenticated user is himself/herself.
    if ((int) $trace->user_id === $user->id) {
        $trace->created_at = (new DateTime('now'))->format('Y-m-d H:i:s');

        file_put_contents('current_user.txt', json_encode($trace));

        $_SESSION['user_id'] = $user->id;

        echo json_encode([
            'success' => true,
        ]);

        return;
    }

    // Ask user if he/she wants to take over.
    echo json_encode([
        'success'  => false,
        'takeover' => true,
        'message'  => 'Another user is logged in. Do you want to take over?',
    ]);

    return;
}

?>

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Login</title>
</head>
<body>
    <form method="post" id="form">
        <div>
            <label for="email">Email:</label>
            <input type="email" id="email" name="email" placeholder="Email" required>
        </div>
        <div>
            <label for="password">Password:</label>
            <input type="password" id="password" name="password" placeholder="Password">
        </div>
        <div>
            <span id="message" style="color: red;"></span>
        </div>
        <button>Log in</button>
    </form>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script>
        $(function () {
            $('#form').submit(function (e) {
                e.preventDefault();
                $('#message').text('');

                $.post('login.php', $(this).serialize(), function (response) {
                    const res = JSON.parse(response);

                    if (res.takeover) {
                        // Ask user if he/she wants to take over. If user confirms, run `confirmed()` function.
                        confirm(res.message) && confirmed();
                        return;
                    }

                    if (res.success) {
                        // Login is successful. Reload or redirect user to another page.
                        location.reload();
                    } else {
                        // Login failed. Incorrect email or password entered.
                        $('#message').text(res.message || '');
                    }
                });
            });

            function confirmed() {
                $.post('confirmed.php', function (response) {
                    const res = JSON.parse(response);
                    console.log(res.data);
                });
            }
        });
    </script>
</body>
</html>
  1. 检查另一个用户是否接管了您页面中当前经过身份验证的用户(在我的情况下为index.php ):
<?php

declare(strict_types=1);

// Start session.
session_start();

// Include helper functions.
require_once 'helpers.php';

?>
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Home</title>
</head>
<body>
<?php if (check_auth()): ?>
    Welcome friend.
<?php else: ?>
    <a href="/login.php">Log in</a>
<?php endif; ?>

<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script>
    $(function () {
        // Check if another user took over currently authenticated user in every 3 seconds.
        setInterval(function () {
            $.post('check.php', function (response) {
                let res = JSON.parse(response);
                if (! res.auth && res.redirect) {
                    location.replace(res.redirect);
                }
            });
        }, 3000);
    });
</script>
</body>
</html>
  1. 实现你的检查逻辑(在我的例子中是check.php ):
<?php

declare(strict_types=1);

// Start session.
session_start();

// Include helper functions.
require_once 'helpers.php';

if (! check_auth()) {
    logout();

    echo json_encode([
        'auth'     => false,
        'redirect' => 'login.php',
    ]);

    return;
}

echo json_encode([
    'auth' => true,
]);

  1. 最后,创建了情况下,你的动作/功能,当用户确认接管( confirmed.php在我的情况):
<?php

declare(strict_types=1);

// Start session.
session_start();

// Include helper functions.
require_once 'helpers.php';

/**
 * Run your action here if user confirms to take over another user.
 */
echo json_encode([
    'data' => 'User confirmed to take over another user.',
]);

经测试,工作正常。 但是你应该根据你的需要定制它。

这里是基本概念。

  • 您需要一个中央存储,其中存储当前活动用户active_user_idlast_updated (数据库/文件/内存缓存/redis 任何你想要的)
  • 您需要为每个会话轮询当前活动用户 - 如果当前用户不是活动用户,他将注销并通知,因此他知道其他人接管了。

流动

  • 用户登录
    • $_SESSION['user_id'] = user_id
    • 如果: $_SESSION['user_id'] !== active_user_id (中央存储 - 见上文)和last_updated < 10s
      • TRUE:登录,将active_user_id更新为$_SESSION['user_id'] last_updated更新为现在; 重定向到主页
      • 错误:显示弹出窗口“接管?” -> ok:与上面的 TRUE 相同,中止:关闭弹出窗口
  • 登录时每 5 秒调用一次check-active.php

check-active.php (伪代码):

  • 如果:来自$_SESSION['user_id'] === active_user_id来自storage $_SESSION['user_id']
    • TRUE:更新storage last_updated 返回“确定”;
    • 错误:调用session_destroy(); 返回“失败”;

frontend伪代码(已登录):

  • 每 5 秒调用一次check-active.php
  • 处理结果
  • 如果:结果 === 'ok'
    • 真:什么都不做
    • 错误:重定向到主页,如 'main.php?message=' 。 urlencode('你被替换了')

为什么要检查last_updated > 10s?

因为有人登录可以关闭浏览器,所以我们不知道会话是否仍然处于活动状态。 所以我们检查last_updated (只要浏览器仍然打开,它就会每 5 秒更新一次)。 如果last_updated大于 10 秒,我们会将其视为“当前没有人处于活动状态”,因此我们不必要求接管。


工作示例

打开这个- 点击“运行”(如果没有运行)。

然后打开两次。 一个在隐身标签中,以获得第二个会话来踢自己。

免责声明:这绝对是实验性的。

这种排序答案是Possible

您可以使用JavaScriptjQuery

使用setInterval userAuserB普通用户登录检查php

setInterval(function() {
    // codes here
},5000); // for 5 seconds

然后在点击功能时得到用户的确认

$('#submit').on('click', function()

带有confirm调用$.ajax函数

if(confirm("Are you sure ?")) {
    // $.ajax codes here
}return false;

userB尝试登录setInterval发送 20 秒等待响应。

20 秒后, userA ip 设置为注销。

setInterval userA收到“注销”然后调用注销 php。

它是基本的ip用户登录信息在检查 php 与数据库。

我刚刚放置了用于此的哪个函数? 不是完整的代码。

注意:下面的代码未经测试,但应该可以让您对要走的路有一个基本的了解。

首先,您应该只撤销当前具有写访问权限的人的写访问权限,因此您的第一个 sql 应该是:

$sql = "SELECT * FROM trace_users where open='true' && write_access = '1'";

其次,由于您已经只选择了具有'open' == "true" ,然后再次检查if($row['open'] == "true") {是多余的。

第三,您应该将用户名放入会话中,以便以后操作和检索登录的用户数据。

第四,您在下面的代码中连续两次执行相同的查询,而不是:

if($result1 = mysqli_query($connect, $sql))

只是放:

if($result1)

现在来解决您的问题:

为了避免在确认后第二次登录尝试来回传递名称和密码,我们可以使用令牌。 另外,那时我想保存用户名,因为我将要使用它,所以在 A 行输入:

$_SESSION['login_token'] = sha1(time());
$_SESSION['user_name'] = $username;

并且我们必须有一种方法将该令牌返回给客户端,然后返回到服务器,以便在脚本中的某处您可以拥有:

if (isset($_SESSION['login_token']) && $_SESSION['login_token']) {
?>
<form id="confirm_form" action="login_script.php" method="POST">
    <input type="hidden" name="login_token" value="<?= $_SESSION['login_token'] ?>">
</form>
<script>
// And the popup:
if (confirm('<?= addcslashes($message, "'/") ?>')) {
    document.getElementById('confirm_form').submit();
}
</script>
<?php
}

我们还希望上面的 PHP 脚本处理会话登录,这也会断开其他用户的连接,因此我们将添加:

if (isset($_POST['login_token'], $_SESSION['login_token']) && $_POST['login_token'] === $_SESSION['login_token']) {
    // block access to any write_access user
    // I am going to make an assumption here - that your write_access column can take the value "-1"
    // I am going to use it as a flag that means that this user needs to be told that his access has been revoked
    mysqli_query($connect, "UPDATE trace_users SET write_access = '-1' where open='true'");

    $_SESSION['pageadmin'] = true;
    $_SESSION['login_token'] = null;
    $open = "true";
    $read_access = "1";
    $write_access = "1";
    $stmt = $connect->prepare("UPDATE trace_users SET open=?, read_access=?, write_access=? WHERE user_name=?");
    $stmt->bind_param('ssss', $open, $read_access, $write_access, $username);
    $stmt->execute();
}

最后,我们需要一个检查权限更改的前端脚本:我将为此使用轮询 + jQuery:

<script>
setInterval(function() {
    $.get('check_permissions.php', function(data) {
        if (data == '-1') {
            alert('your write access is revoked');
        }
    });
}, 5000);
</script>

和 check_permissions.php 是:

$stmt = $connect->prepare("SELECT write_access FROM trace_users WHERE user_name = ?");
$stmt->bind_param('s', $_SESSION['user_name']);
$stmt->execute();
$stmt->bind_result($status);
$stmt->fetch();
echo $status;

if ($status == -1) {
    // and update status of this user that he has no write permissions but no longer needs to be warned
    $stmt = $connect->prepare("UPDATE trace_users SET write_access = 0 WHERE user_name = ?");
    $stmt->bind_param('s', $_SESSION['user_name']);
    $stmt->execute();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM