0

PHPで一種のWebアプリを構築しています。基本的にユーザーがオンラインであることをサーバーに伝えるセッション変数にトークンを保存する方法でログインフォームがあります(これはデータベースにも保存されます)。このトークンは、ログイン フォームが表示されるとクリアされます (新しいログイン... またはログアウト時 - ここのコードには示されていません)。また、ログインの成功時に session_id() をデータベースに保存します。

2 つのセッションが (同じブラウザーまたは異なるブラウザーで) 開かれるのを防ぐために、2 種類のチェックを行います。

  1. ユーザーがログイン後に 2 番目のタブのみを開く場合、このトークンと http リファラーを確認します。トークンが空ではなく (誰かがログインしていることを意味します)、http リファラーが空である場合 (新しいタブ/ウィンドウが開かれていることを意味します)、エラー メッセージをエコーし​​ます (「既にセッションが開いています...」)。

  2. ログインする前にユーザーが 2 つのタブを開いている場合、このトークンと、DB および現在の DB の session_id() をチェックします。トークンがそこにあり (誰かがログインしていることを意味します)、DB と現在の session_id() が同じであれば (つまり、まだ同じブラウザーを使用していることを意味します)、エラー メッセージをエコーし​​ます (「既に開いているセッションがあります.. .")。ここで session_id() が異なる場合は、別のブラウザーを使用していることを意味し、これについてもチェックしています。

同時に、ユーザーがログインフォームを再投稿できないようにしようとしています。つまり、ログイン直後にリロードをクリックしないようにしたいのです。

問題:
上記のセットアップでは、リロードをクリックすると、トークンがそこにあり、session_id() も同じであるため、サーバーは 2 番目のブラウザー タブ ログイン (上記のケース #2) であると見なします。エラーメッセージが表示されます (「既に開いているセッションがあります...」)。

あまりにも組み合わせて、ログインフォームのリロード時に何も起こらないことを確認する方法はありますか?

コードは次のようになります (不要なコードを削除しようとしましたが、100% 正しくない場合は申し訳ありません)。

<?php function LoginForm() { 
$_SESSION['token'] = ''; ?>
<form action="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'].$_SERVER['QUERY_STRING']); ?>" method="post">
    Please enter your login details</div><br />
    Login ID<br />
    <input type="text" name="userid" /><br /><br />            
    Password<br />
    <input type="password" name="password" /><br /><br />
    <input type="submit" name="login" value="Login" />
</form>
<?php }

if (!empty($token_in_DB) AND !isset($_SERVER['HTTP_REFERER'])) {
    echo "You are already logged in on another tab / window";
    exit();
} elseif (isset($_POST['login'])) {
if (!empty($token_in_DB)) {
    if ($session_in_DB == session_id()) {
            echo "You are already logged in on another tab / window";
            exit();
    } else { 
            echo "You are already logged in on another browser / computer";
            exit();
            }
    } elseif (/* password is ok */) {       
        // login
        // set token session variable
        // add token to db   
    }
} elseif (empty($_SESSION['token'])) {
    LoginForm();
} ?>
4

1 に答える 1