11

Internet Explorer を使用している特定のユーザーのセッション変数を PHP が保存しない Web サイトに問題があります。しかし、Internet Explorer を使用している他の一部のユーザーにはまったく問題はなく、他のブラウザーを使用しているユーザーにも問題はありません。

Web サイトに他のコードが含まれていないことを確認するために、次の 3 つの小さなスクリプトを作成しました。

test.php:

<?php
session_start();

function logMsg($text) {
    $filename = dirname(__FILE__) . "/test.log";
    $fh = fopen($filename, "a") or die("Could not open log file.");
    fwrite($fh, date("d-m-Y, H:i")." - $text\n") or die("Could not write file!");
    fclose($fh);
}

ob_start();
var_dump(session_id(), $_SESSION, $_SERVER, $_REQUEST);
$content = ob_get_clean();

logMsg("test.php");
logMsg($content);

$_SESSION['test'] = array('test' => 'lalala');
$_SESSION['count'] = 1;
?>
<a href="test2.php">Next</a>

test2.php:

<?php
session_start();

function logMsg($text) {
    $filename = dirname(__FILE__) . "/test.log";
    $fh = fopen($filename, "a") or die("Could not open log file.");
    fwrite($fh, date("d-m-Y, H:i")." - $text\n") or die("Could not write file!");
    fclose($fh);
}

ob_start();
var_dump(session_id(), $_SESSION, $_SERVER, $_REQUEST);
$content = ob_get_clean();

logMsg("test2.php");
logMsg($content);

$_SESSION['count']++;
?>
<a href="test3.php">Next</a>

test3.php:

<?php
session_start();

function logMsg($text) {
    $filename = dirname(__FILE__) . "/test.log";
    $fh = fopen($filename, "a") or die("Could not open log file.");
    fwrite($fh, date("d-m-Y, H:i")." - $text\n") or die("Could not write file!");
    fclose($fh);
}

ob_start();
var_dump(session_id(), $_SESSION, $_SERVER, $_REQUEST);
$content = ob_get_clean();

logMsg("test3.php");
logMsg($content);

の期待される出力は次のvar_dump($_SESSION)ようになります。

array(0) {
}

array(2) {
    ["test"] => array(1) {
        ["test"] => string(6) "lalala"
    },
    ["count"] => int(1)
}

array(2) {
    ["test"] => array(1) {
        ["test"] => string(6) "lalala"
    },
    ["count"] => int(2)
}

ただし、問題のあるユーザーの出力は次のとおりです。

array(0) {
}

array(0) {
}

array(1) {
    ["count"] => int(1)
}

つまり、これらのユーザーのセッション変数は保存されません。ただし、問題のあるユーザーのセッション ID は、3 つのテスト ページすべてで同じです。

誰かがこれが何であるか考えていますか? 私が知る限り、問題のあるコードは数年間機能しており、先月かそこらで問題が発生し始めました。

編集

コメントの質問への回答:

  • ローカル マシンで問題を再現できません。
  • IE7 と IE9 のユーザーから問題の報告があります。しかし、他のバージョンについてはまだ報告されていない可能性があるため、問題がないと断言することはできません。
  • 問題のあるユーザーのブラウザーでは Cookie が無効になっていないため、PHPSESSID Cookie がサーバーに送信されます。
  • マシン名に - または _ はありません ( https://stackoverflow.com/a/306601/534109 )。
  • session_regenerate_id() でセッション ID を再生成しても、問題のあるユーザーの結果には影響しません。
  • 問題のあるユーザーのタイムゾーンと時間の設定は、サーバーと同じです。

編集 2

@nl-x がコメントで述べたように、データは 2 番目のリクエストに保存されます。そこで、テスト シナリオを調整し、別のステップを追加して、後続のリクエストでセッションが機能するかどうかを確認しました。そして、これが事実です。セッション データ セットはstep2.phpstep3.phpリクエスト間で保存されます。

では、最初のリクエストのセッション データが失われ、その後のリクエストでは失われないのはなぜでしょうか。

4

4 に答える 4

5

問題を抱えていたユーザーは全員 Chrome Frame をインストールしていたことがわかりました。ローカル マシンに Chrome Frame をインストールしてこれを確認したところ、この場合は問題を再現できました。

問題は、サーバーに Suhosin がインストールされていることが原因でした。次の Suhosin 設定が有効になりました。

suhosin.session.cryptua
suhosin.cookie.cryptua

これは、ユーザー エージェント文字列もユーザーのセッションの識別の一部であることを意味します。通常、これは問題ではありませんが、Chrome フレームがインストールされているユーザーの場合、ユーザー エージェント文字列は最初のリクエストと後続のリクエストで異なります。これらの Suhosin 設定を無効にすると、問題はなくなりました。

于 2013-05-30T18:57:14.680 に答える
2

PHP のセッション メカニズムの特定の知識を持つ誰かを待つ代わりに、私はこれを仮定します。

私は主に ASP.NET を使用しており、Sessionオブジェクトは Cookie を使用して要求間でデータを永続化します。PHP が同じように機能する場合、最も明白な結論は、セッションの問題を抱えているユーザーは Cookie を無効にしているか、ホワイトリストに登録されたドメインのみが Cookie を設定できるようにするソフトウェアを使用しているということです。この理論を裏付ける事実を見つけることができるかどうかを確認します...

PHP マニュアルから ( http://www.php.net/manual/en/intro.session.php ):

これは、ユーザー側の Cookie に保存されるか、URL で伝達されます。

于 2013-05-29T08:31:12.920 に答える
1

最初のリクエスト後、Cookie が失われたように見える理由を正確に説明することはできません。(それが私が推測していることです。)そして、2番目のリクエストが失われないのはなぜですか。

おそらく実際にはキャッシングの問題です。開発者ツールを確認し、[ネットワーク] タブで何が起こっているかを正確に確認してください。最初のリクエストは 200 - OK で受信され、応答には Cookie ヘッダーが含まれていますか? それとも、コメントの1つが示唆したように、実際にキャッシュされていますか?

しかし、最終的には、正しいセッションIDの受け渡しを実際に実装する必要があります(読んでください)。これは、Cookie を使用したくない、または処理できない人を対象としています。

基本的には、次の変更を意味します。

<a href="test3.php">Next</a>

の中へ:

<a href="test3.php?<?php echo htmlspecialchars(SID); ?>">Next</a>

また:

--enable-trans-sid を有効にする

セッションが Cookie によって渡されないことを PHP が認識すると、URL で安全性の低い方法でセッションを提供します。特にこの場合、 が必要になりますsession_regenerate_id()

編集: そうそう、私はそれを前に言及したかったのですが、それはあり得ないと思いました. しかし、考え直して、私はまだそれについて言及します!:

デフォルトでは、Cookie はドメイン固有です。ユーザーがhttp://yourdomain.com ( www.なし) にアクセスし、2 番目の要求がhttp://www.yourdomain.comに送信された場合、Cookie はドメインの変更に耐えられません! したがって、セッションに影響を与えます。

これを修正するには、セッション cookie ドメインを設定するか、常に同じドメインを使用します (www の有無にかかわらず)。

于 2013-05-29T08:58:31.170 に答える
-1

まず、php.ini セッションの構成、特に Cookie の有効期間を確認する必要があります。質問にセクションを追加します。エラーが発生しているクライアントに Fiddler をインストールし、セッションの完全な http ダンプを生成します。これは、問題を簡単に追跡するのに役立ちます。

于 2013-05-29T09:19:47.647 に答える