スレッド表示 | フラット表示〕 全トピック 920 件中 16 番目 次≫ ≪前

session_regenerate_id 後でセッションが空になっている

created: 2010-03-12 23:49 | modified: 2010-03-13 17:39 | reply: 4

[4361] session_regenerate_id 後でセッションが空になっている

user: ただの課長 | created: 2010-03-12 23:49
よろしくお願いいたします。

ログイン処理をテストしています。

login.php でIDとパスワードを入力してもらい、自分自身へPOSTしてIDとパスワードをチェックします。入力が正しければ、header('location:~'); をして、index.php に遷移するようにしています。

location をする前に、session_regenerate_id(true) を実行し、その直後、sha1 を通した session_id を セッション変数に保存しています。

問題は location した index.php で起こります。
index.php の先頭では、sha1(session_id()) と 保存セッション変数 を比較するのですが、何故か 保存セッション変数 が空になっているのです。
さらにその時 session_id() が返す値が regenerate する前の session_id になっているのです。

session_regenerate_id しなければ問題なく動作するのですが、ログイン後に session_regenerate_id をした方が良いというネットの記事を見かけるので入れてみたのですが、入れると上記の状態になり先に進めません。

何が間違っているかご指摘いただけると助かります。
reply: 4362 返信 編集 削除

[4362] 現象の再現コード

user: ゆうじ | created: 2010-03-13 01:39
こんばんわ。

不可解な現象を再現出来る最小限のコードがあればいいのですが
とりあえず、想定される動きをする方のコードを書いてみました。

<?php
/**
* index.php
*/
error_reporting(E_ALL);
session_save_path('/home/userdir/tmp/sess');
session_start();

if (!isset($_SESSION['sha1'])) {
header('Location: http://localhost/form.php');
exit();
}
?>
<p>session_id: <?php echo session_id(); ?></p>
<p>sha1(session_id): <?php echo sha1(session_id()); ?></p>
<p>$_SESSION[sha1]: <?php echo $_SESSION['sha1']; ?></p>
<p><a href="form.php">Login form</a></p>

<?php
/**
* form.php
*/
error_reporting(E_ALL);
session_save_path('/home/userdir/tmp/sess');
session_start();

?>
<p>session_id: <?php echo session_id(); ?></p>
<p>sha1(session_id): <?php echo sha1(session_id()); ?></p>
<?php if(isset($_SESSION['sha1']) && is_string($_SESSION['sha1'])): ?>
<p>$_SESSION[sha1]: <?php echo $_SESSION['sha1']; ?></p>
<?php else: ?>
<p>$_SESSION[sha1]: (none)</p>
<?php endif; ?>
<form action="http://localhost/login.php" method="post">
Name: <input type="text" name="name" value="">
<br>Pass: <input type="password" name="pass" value="">
<br><input type="submit" value="Send">
</form>

<?php
/**
* login.php
*/
error_reporting(E_ALL);
session_save_path('/home/userdir/tmp/sess');
session_start();

if ('hoge' !== $_POST['name'] || 'hoge' !== $_POST['pass'] ) {
if (isset($_SESSION['sha1'])) {
unset($_SESSION['sha1']);
}
header('Location: http://localhost/form.php');
exit();
}

session_regenerate_id(true);
$_SESSION['sha1'] = sha1(session_id());
header('Location: http://localhost/index.php');
exit();
?>

自宅PC の PHP5.2 では動きましたのでお試しください。
これが想定通りの動きをしなければ環境の違いに原因があるかも、
また動くようならこの部分以外のコードに原因がある、
といった具合に切り分けられます。

コードの場合は、現象を再現出来る
最小限のコードを書いてみると原因が絞り込めます。
Parent: 4361  reply: 4363 返信 編集 削除

[4363] ありがとうございます

user: ただの課長 | created: 2010-03-13 13:57
こんにちは。

コードサンプルありがとうございます。
サーバーに3ファイルを置いて動作確認したところ、問題なく動作しました。
セッションもregenerateされ、form.phpに戻ってもsessionは保持されたままでした。

コードの問題ということがわかりました。
自分の書いたコードも、同じぐらい単純なものだったのですが、大きく違うのは、ゆうじさんが書いた form.php に login.php を足して1ファイルにしたlogin.php というところです。
単純にファイル数を押さえたいという意図からそうしていました。ゆうじさんのコードを見習って3ファイル構成にしたいと思います。
基本的にPOST先は自分自身にしない方が正しい(好ましい?)のでしょうかね。

ありがとうございました。
Parent: 4362  reply: 4364 返信 編集 削除

[4364] リクエストの送信先の件

user: ゆうじ | created: 2010-03-13 16:59
解決したようでひと安心です。

> 基本的にPOST先は自分自身にしない方が正しい(好ましい?)のでしょうかね。

フレームワークなんか使うと
リクエストの送信先がindex.phpひとつだけというのもありえるので
送信先が自分自身というのにこだわらなくてもいいと思います。

ただ、1年経って何をやってたのかわからなくなる
と思ったら分けておくといかがでしょう。
私は「保守しやすい」というのを基準にしています。
Parent: 4363  reply: 4365 返信 編集 削除

[4365] なるほど

user: ただの課長 | created: 2010-03-13 17:39
> 送信先が自分自身というのにこだわらなくてもいいと思います。

そういっていただけると、何か晴れたような気持ちです。
大げさかもしれませんが周囲に詳しい者がいないので
悩むことが多いのです。
昔ですがASP.NETをちょっとだけかじったことがあり、
そこでポストバックと呼ばれる手法で学んだものですから
PHPもそうなのかなって思っていたのかもしれません。

フォームと処理を分ければPHPファイルの用途が明確になり、
ゆうじさんのおっしゃるように保守しやすくなると思いました。
ありがとうございました。
Parent: 4364  返信 編集 削除
スレッド表示 | フラット表示〕 全トピック 920 件中 16 番目 次≫ ≪前
ページの一番上へ
Googleグックマークに登録 Yahooグックマークに登録 livedoorクリップに登録 @niftyクリップに登録 はてなブックマークに登録 deliciousに登録 Buzzurlに登録 FC2ブックマークに登録
最近更新された掲示板トピックス
管理人Blog
Yahoo Search

最近更新したNote
PHPマニュアル
今日のブックマーク
PHPマニュアル関数検索
関数名を入力し検索ボタンをクリック↑