TOMOYUKI-K
@TOMOYUKI-K

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

phpのセッションの概念について

解決したいこと

phpのsession有効期限の概念について何度調べても理解できず、、、
どなたか心優しき方、ご教授いただければ幸いです。

現在ログイン情報を持ちまわるWEBサイトを構築中です。
以下の要領でファイルを構成しました。

//ファイルA
<?php
session_start();
//ログイン情報をもらった前提で
$_SESSION['user'] = $_POST['user'];
header('ファイルB or ファイルC');
?>


//ファイルB
<?php
session_start();
if(isset($_SESSION['user'])){
  echo "こんにちは".$_SESSION['user']."さん";
 処理 B;
}else{
  header('ログインフォーム');
}
?>


//ファイルC
<?php
session_start();
if(isset($_SESSION['user'])){
  echo "こんにちは".$_SESSION['user']."さん";
 処理 C;
}else{
  header('ログインフォーム');
}
?>

・要は最初にログインフォーム(上記3ファイルからは割愛)からログイン情報をもらう
・ファイルAでセッション変数に保存
・ファイルBもしくはCで持ち回りユーザーに応じた処理を行う

発生している問題・エラー

正確に測れていませんが約30~40分程度でログインが解除されてしまいます。
デフォルトでなっていそうな24分は超えることを確認しました。
→$_SESSION['user']が確認できずheader関数でログインフォームへ飛ばされる。

補足

ファイル環境がレンタルサーバーのためiniファイルに詳細設定ができない状況です。
具体的にはXserver無料プランです。
php.ini設定でそれと思しきものの変更は試しましたがうまくいきませんでした。
無料プランの為、サポートが無く自分で調べるに至った次第です。

教えていただきたいこと

①ファイルを交互に行き来した場合でも1セッション/1セッションファイルを参照となるのでしょうか?
 
②有効期限の概念
 →セッションが途切れるのはどのタイミングなのでしょうか?一番最初のsession_start()からの期限?それとも最終読み込み時から?
 →途切れるの実態は、セッションファイルの消滅なのか、セッションID(クッキー)の消滅なのか

③例えばファイルBから全く動かず有効期限を過ぎて再アクセスする場合、session_start()時には新しいセッションの開始という扱いになるのでしょうか?
 →質問④に繋がるかもですが、その場合セッションIDは新旧2つ存在になると思います。その後は2つを同時に送信/参照ということになるのでしょうか?

④ガベージコレクションという仕組みを知りましたが、これは有効期限を過ぎた場合にはすぐにファイルを参照できなくなるのでしょうか?
 それともデフォルトの1/1000回を偶然避ければ半永久的に参照できるのでしょうか?
 →古いセッションIDをメモで控えていれば相当時間過ぎても参照ができる?

⑤有効期限延長はini_set()関数で合っていますでしょうか?
 →あっていた場合、記述は一番最初にsession_start()を行うファイルAのみでいいでしょうか?それとも全ファイルでしょうか?
 →全ファイルの場合、有効期限は毎回更新される?

0

2Answer

①ファイルを交互に行き来した場合でも1セッション/1セッションファイルを参照となるのでしょうか?

イメージとしては、webサーバにアクセスしてからブラウザを閉じるまで1セッションになります。
正確には、サーバのセッション情報が破棄されるまで、になると思います。

②有効期限の概念

正確な情報元を確認できなかったのですが、session_start()の時に確率でガベージコレクションが実施され、その時に有効期限が切れているセッションが全て破棄されるようです。

③例えばファイルBから全く動かず有効期限を過ぎて再アクセスする場合、session_start()時には新しいセッションの開始という扱いになるのでしょうか?

session_start の説明では、「新しいセッションを開始、あるいは既存のセッションを再開する」、となっています。
再アクセスときにセッションが破棄されていれば新しいセッションを開始、ということになりますね。

④ガベージコレクションという仕組みを知りましたが、これは有効期限を過ぎた場合にはすぐにファイルを参照できなくなるのでしょうか?
 それともデフォルトの1/1000回を偶然避ければ半永久的に参照できるのでしょうか?

前述の通り、その確率で破棄されるようなので、偶然避ければそうなるのかもしれません。
ただ、誰がアクセスしたかによらず、実施されれば全て破棄されるようなので、
それなりにアクセスがあれば半永久的というのは難しいと思います。
しかし、マニュアルでは次のように書いています。

開発者は session.gc_maxlifetime によるセッションの期限切れに依存しては いけません。 攻撃者は、認証済みのセッションも含めて、期限切れを防いで悪用を続けるため、 ターゲットのセッションIDに定期的にアクセスしている可能性があるからです。
そのかわりに、開発者はタイムスタンプベースのセッション管理を実装しなければなりません。

必要に応じて、正しく破棄されるようにする必要があります。

⑤有効期限延長はini_set()関数で合っていますでしょうか?

有効期限の設定はsession.gc_maxlifetimeですが、PHP_INI_ALLになっているのでini_set()やphp.iniなどで設定できます。(サーバの状況にもよります)
実行時設定
どこで設定を行うのか

 →あっていた場合、記述は一番最初にsession_start()を行うファイルAのみでいいでしょうか?それとも全ファイルでしょうか?

ini_setによる設定は、スクリプトの実行中は新しい値を保持し、スクリプト終了時に元の値へ戻されます。
つまり全ファイルに必要です。

1Like

Comments

  1. @TOMOYUKI-K

    Questioner

    @blue32a様
    返信遅れまして大変申し訳ございませんでした。
    まさかこんなに早くコメントいただけるとは思わず・・
    早急なコメントありがとうございます!!

    とてもよく理解できました。
    まだ実践として体に染みついていないので実際にコードを打って
    挙動を確認しながら覚えていこうと思います!

    因みに本件はXserverがiniファイルを詳細まで設定できないところで
    つまづいていたのですが有料プランにしてサポート受けながら詰めていこうと思います。

③例えばファイルBから全く動かず有効期限を過ぎて再アクセスする場合、session_start()時には新しいセッションの開始という扱いになるのでしょうか?
 →質問④に繋がるかもですが、その場合セッションIDは新旧2つ存在になると思います。その後は2つを同時に送信/参照ということになるのでしょうか?

2つのセッションファイルにアクセス、ということは起きません。

  • CookieにセッションIDがある場合、session_start()は、Cookieで指定されたセッションIDのファイルを探しに行き、削除済みなら、空データで新規作成します。
    • この場合、IDは増えていません。
  • Cookieにない場合、新しいセッションIDを発行して、対応する新規ファイルを作り、Cookieの設定を行います。
    • セッションファイルがある状態でCookieを消去した場合、2つ目のファイルができることになりますが、1つ目のIDはもうだれも知らないので、実質アクセスできなくなります。

標準では、以下の条件でセッションが切れた状態とみなせます。

クライアントサイド

  • セッション用のCookie有効期限が切れて、保持されなくなったとき
    • この時点で、アクセス先がわからなくなるので実質セッション切れ
      • ※強引に同じセッションIDを設定すると、以前の情報にアクセス可能
    • ブラウザ側での処理なので、PCの時計がずれていると意図した時間に切れなかったりする

サーバサイド

  • セッションファイルが削除されたとき
    • ガベージコレクションが起動されたとき、最終更新日時が一定以上経過しているすべてのセッションファイルが削除される
      • GC起動は、session_start()するすべてのアクセスで確率発生
      • セッションファイルが更新されなくなってから、一定期間以上経過した物が消える

デフォルト設定では、セッション変数に書き込みがない場合、セッションファイルが更新されません。今回の場合、この条件に当てはまってしまったのではないでしょうか。
session.lazy_write を無効にするか、何らかの書き込みを行うことで回避できます。


※実際のところ、PHPでは、サーバ側の時間による厳密な意味でのセッション有効期限は規定されていません。どうしても厳密に管理したい場合、セッションデータ内に開始日時や更新日時を保持し、自前で破棄する処理を作る必要があります。

1Like

Comments

  1. @TOMOYUKI-K

    Questioner

    @ahsgw様
    こちらも返信遅くなり申し訳ございません。
    実例をもとに解説してくださりより深く理解することができました。
    おっしゃる通り自前で挙動をコントロールしたほうが安全で無難なのかなと
    思いましたのでそのようなコードを頑張ってやってみようと思います!
    コメントいただき誠にありがとうございました。

Your answer might help someone💌