簡體   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