5

一部のセッション機能と、Chrome のプリフェッチ/レンダリングの方法に問題があります。フォーラム ソフトウェア (esoTalk) をカスタム laravel 4.3 アプリと接続しようとしています。フォーラムとアプリが認証の詳細を共有できるようにするphpセッション(組み込みのlaravelセッションに加えて)をlaravelに作成させる認証イベントリスナーがあります。フォーラムへのアクセス時に、ユーザーがログインしていなくても、この共有情報が存在する (ユーザーが laravel アプリにログインしている) 場合、フォーラムはセッションで利用可能な情報を使用してそのユーザーをログインさせます。

ほとんどの場合、これは正常に機能しますが、Chrome のプリフェッチが問題を引き起こしているようです。デバッガーを使用してフォーラムを監視すると、フォーラムの URL を入力すると、クロムを入力する前にフォーラムにアクセスできることがわかります。デバッガーを実行すると、必要なすべての処理が実行され、ログインに成功したことがわかります。最後のステップとして、フォーラムはセッション ID を再生成してハイジャックを停止します。これが壊れるところです。Chrome は新しいセッション ID (http SetCookie ヘッダー経由で送信) を無視するように見えるので、Enter キーを押すと、元のセッション ID を使用してフォーラムに移動します (そしてまったく新しい要求を行います)。この ID は存在しないため、新しい ID を設定すると、ログイン状態が失われます。ユーザーにとって、これはログインしていないように見えます。

これを回避する方法についての提案を求めて、高低をグーグルで検索しました。セッション ID の再生成を削除するのは、セキュリティ上の目的に役立つため、私は嫌です。また、クロムのプリフェッチ/レンダリングを無効にすることもできません。全体として、私は少しピクルスになっているようです。

これを再現するコードをいくつか作成しました。ただし、事前レンダリングの開始に依存しています (そのため、アドレス バーから各ファイルに何度もアクセスする必要があります)。

// test1.php

<?php

function regenerateToken()
{
    session_regenerate_id(true);
    $_SESSION["token"] = substr(md5(uniqid(rand())), 0, 13);
    $_SESSION["userAgent"] = md5($_SERVER["HTTP_USER_AGENT"]);
}

// Start a session.
session_set_cookie_params(0, '/');
session_name("SessionBork_Test_session");
session_start();

$_SESSION["SentryUserId"] = '99';

regenerateToken();

header('Content-Type: text/plain');
foreach ($_SESSION as $k => $v) {
    echo $k . " = " . $v . "\n";
}

test1.php に続いて test2.php にアクセスすると、一連のセッション変数の出力が表示されます。プリレンダリング/フェッチが開始されるとすぐに、壊れたメッセージが表示され始めます。

// test2.php
<?php

function regenerateToken()
{
    session_regenerate_id(true);
    $_SESSION["token"] = substr(md5(uniqid(rand())), 0, 13);
    $_SESSION["userAgent"] = md5($_SERVER["HTTP_USER_AGENT"]);
}

// Start a session.
session_set_cookie_params(0, '/');
session_name("SessionBork_Test_session");
session_start();

if (empty($_SESSION["token"])) regenerateToken();

// Complicate session highjacking - check the current user agent against the one that initiated the session.
if (md5($_SERVER["HTTP_USER_AGENT"]) != $_SESSION["userAgent"])
    session_destroy();

// Log in a the user based on the SentryUserId
// ... logging in, setting userId, regenerating session
$_SESSION["userId"] = '10';
regenerateToken();

header('Content-Type: text/plain');
foreach ($_SESSION as $k => $v) {
    echo $k . " = " . $v . "\n";
}
if ( ! isset($_SESSION['SentryUserId'])) echo "\n--\nPrerendering brokeded me.";

IDE などで xdebug に接続できる場合は、隠し prerender が test2.php にヒットし (これは応答で完全に正しいように見えます)、Enter キーを押すと、その後の実際のヒットが表示されます。あなたは。

4

1 に答える 1

1

この問題を回避する 1 つの方法は、プリフェッチを検出し、それらのロードで新しいセッション ID を生成しないことです。さまざまなブラウザーでのプリフェッチの検出に関する情報については、このスタック オーバーフローを参照してください: Google Chrome によるプリロード要求を検出するための HTTP ヘッダー

さらに、セッションのハイジャックを防止するためのより良い方法があると主張したいと思います (たとえば、セッションを IP アドレスやブラウザ署名などに関連付ける)。

さらに、コードに 2 番目のバグがある可能性があります。呼び出しsession_destroy()によってセッションが破棄され、ユーザーのセッションが閉じられます。session_start()に電話する前に電話する必要がありますsession_regenerate_id()。こちらのドキュメントとこちらの例を参照してください

于 2015-05-03T12:45:34.203 に答える