• ベストアンサー
  • 困ってます

初歩的な質問 セッション管理について

  • 質問No.5212893
  • 閲覧数812
  • ありがとう数6
  • 回答数7

お礼率 83% (628/754)

セッション処理をしたいと考えていますが、
分からない点が多く困っています。

したいと思っていることは、「ログイン」的な処理です。

訪問者がブラウザを閉じても、サイト設計者が設定した「期間」、
ログイン状態をキープさせておけるような仕様です。

※よくあるタイプです。
(特段、難しいことや変わったことをしようとしてはいません。)

ただ、ちょっと変わっている点は、ログインはパスワード無しで行います。
フォーム(POST)でボタンをクリックしたら、誰でもログインできるようなものです。

で、上記処理をする方法として、大きく分けて、
(1)クッキー($_COOKIE)を使う方法と、
(2)セッション($_SESSION)を使う方法とがあるように思っています。

(1)の方法だと、
データそのものをクライアント側に保存させるのでセキュリティ上、やや難があり、
(2)の方法だと、「キー(セッションID)」だけをやりとりするので比較的安全、
ということをよく耳にします。

ただ、パスワードを扱うわけではないので、この場合には、
(1)の方法でもアリな気がしています。

しかし、今後、パスワード形式に移行しないとも限らないので、
(2)を使った方法で話を進めたいと思います。

パスワードのやりとりがないのなら、(1)の方が断然楽でいいよ~
ということであれば、話は変わってきます。
その場合には教えて下さい。

(※質問文の中で、私は随所に変なことを言っている可能性がありますので、
適宜、ご指摘頂けると嬉しく思います。)

話を戻しまして、
ここからは、前述の(2)の方法で話を続けさせて頂きます。

セッション処理の流れについてですが、
セッションIDをクライアントに送りつけ、保存させる方法は、
session_start()をスクリプト先頭に書き、
$_SESSION['login'] = 'おまえはもう、ログインしてる…。';
と、どこかに書くことで、

この$_SESSION['login']値を保持している間、訪問者は、
サイト内のページを、ログインされた状態として閲覧できる
と、私は考えています。
何か変なことを言っていましたら、ご指摘下さい。(★ポイント1)

//-----------------------------------

次に、セッション保持期間の設定の方法についてですが、
ネット上で調べた所、
ini_set("session.gc_maxlifetime", "1440");
のように設定できると書いてありました。

このini_set()による設定が、どう作用するのか、
この点もよく分からずにいます。(★ポイント2)

session.gc_maxlifetimeの設定自体は、スクリプト終了とともに、
Master Valueに戻されるようですが(PHPマニュアルより)、
私が気になっているのは、
そのスクリプトで生成したセッションの保持期間は、どうなっているのか?
ということです。

ちょっと乱暴な書き方をしますが、
例えば、

php.ini上(つまり、Master Valueの設定値)では、
session.gc_maxlifetime:1440
というような設定 の場合に、

スクリプトAの中で、
ini_set("session.gc_maxlifetime", "~仮に24時間としておきます~");
のように書き、
そのあとに、
$_SESSION['login'] = 'おまえはもう、ログインしてる…。';
と書いた場合、
クライアントには、$_SESSION['login']のデータは24時間保持される、
ということでしょうか。

つまり、
スクリプト内に書いた、
ini_set("session.gc_maxlifetime", "~仮に24時間としておきます~");
という記述は、
そのスクリプトでセッションIDをクライアントに与える場合の「そのセッションIDの保持期間」のみ
を設定できる、という理解でよろしいでしょうか。

当たり前のことをお聞きしているかもしれませんが、
どなたか、どうか、よろしくお願い致します。

質問者が選んだベストアンサー

  • 回答No.3
  • ベストアンサー

ベストアンサー率 79% (381/480)

PHPのセッションは、
ランダムで且つユニークなIDを生成し、サーバのセッションのテンポラリディレクトリにそのIDを保存して、CookieにそのIDを書き込みます。
なので、SESSIONを使うといっても基本的にはCookieも使っているわけです。

ということは、
http://www.php-ref.com/web/02_session_set_cookie_params.html
こちらの、session_set_cookie_params関数を使って、cookieの生存時間を設定すれば良いですね。cookieが削除されてしまえば、ユーザがサーバに残されているIDを照合出来なくなるので、自動的にログアウトされます。
ただ、cookieはクライアント側にファイルとして記録されておりますので、ユーザが書き直す場合が当然あります。
そこで、多重でチェックする意味で、ログインが発生したタイミングで、セッション変数に、ログインされた時間を記録します。
<?php
//ログインされた。
$_SESSION['logintime'] = time();
?>
で、ログイン中の処理として
<?php
define('LIFETIME', 86400)//24時間

$max = $_SESSION['logintime'] + LIFETIME;

if($max < time()){
//24時間以上たっていた場合の処理
//例えば、書き込んだクッキーを削除して、sessionも閉じる
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(), '', time()-42000, '/');
}
session_destroy();

exit('ログアウト');
}

?>
といった感じで終了してやります。


また、PHPで値を単純にCookieに書き込む場合は、
http://nyx.pu1.net/practice/cookie/cookie3.html
こちらのように使います。
補足コメント
march4

お礼率 83% (628/754)

>SESSIONを使うといっても基本的にはCookieも使っている

この仕組みは、頭に入っていましたが、
$_SESSIONの有効期限を決めるということが、
$_COOKIEの有効期限を決めることと同じこと、
ということが、頭の中で整理されていませんでした。
よって、この点の理解は、私にとってかなり大きな収穫と言えます。

頂いた回答の中盤以降は私にはやや難解でした。汗

・session_set_cookie_params()関数
→設定できる項目
(有効期限、パス、ドメイン、セキュリティ、http)

これと、

・setcookie()関数
→設定できる項目
(クッキー名、クッキー値、有効期限、パス、ドメイン、セキュリティ)

が回答の中で登場しました。
私は、どちらの使用経験もありません。

>こちらの、session_set_cookie_params関数を使って、
>cookieの生存時間を設定すれば良いですね。

生存時間(有効時間)を決める場合、
上記両関数、どちらでも可能であるように感じましたが、
ここで、session_set_cookie_params関数の方を選ばれたことには、
何か根拠はあるのでしょうか。


>cookieが削除されてしまえば、
>ユーザがサーバに残されているIDを照合出来なくなるので、
>自動的にログアウトされます。

ここについては、理解OKです。


>ただ、cookieはクライアント側にファイルとして記録されておりますので、
>ユーザが書き直す場合が当然あります。

サーバがクライアントへ送ったものとは違ったものに、
クライアント側で書き換えてしまわれると、
有効期限内のクッキーであったものでも、
「別物」に変えられてしまうために、
IDの照合ができなくなるわけですよね。

>そこで、多重でチェックする意味で、ログインが発生したタイミングで、
>セッション変数に、ログインされた時間を記録

えっと・・・。

サーバさんが、アクセスしてきたクライアントさんに対し、
「あなたは、あの時のあの人だよね」
という照合をする際の照合方法を2重にしておく、という理解でよろしいでしょうか。
(もちろん、ここでの2重システムにするしないについては任意である、
ということなのでしょうが、hogehoge78さんの書かれたこの2重のソースについて
詳しく知りたいと思いますので、ここでは突っ込んで質問を続けます。)

で、その2重というのは、
・最初に書かれていた、$_COOKIEによる方法
と、もう1つ、
・$_SESSIONによる方法
ということですよね。

$_COOKIE値が書き換えられてしまう可能性をカバーするために、
$_SESSIONも利用しておく、という感じでしょうか。

ただ、ここで疑問なのは、$_SESSIONも結局は、COOKIEを利用している、
ということでしたので、$_SESSIONによってクライアントに送りつけたセッションIDは、
クライアント側で書き換えられたりしないのでしょうか。

(もちろん、され得るけれども、2重にしとけば、より堅牢だろう、ということでしょうか。)

次に、ソースについて。
気になった箇所がいくつかあります。

(1)
//----------------------------

if (isset($_COOKIE[session_name()])) {

//----------------------------

session_name()は、デフォルトでは、「PHPSESSID」のようですが、
これは、通常、このままの値で使っていて良いものなのでしょうか。
(セキュリティ上、変更しておいた方が良かったりしますか?)

現在、私はセッションIDと、セッション名が頭の中でこんがらがっています。汗
両者の関係が、掴めそうで掴めないのです。。

>$_COOKIE[session_name()]

また、↑これがどういうことをしようとしているのかについても、
理解できないでいます。。涙
$_COOKIE[]に、session_name()が入っている?!
つまり、デフォルトでは、
$_COOKIE[PHPSESSID]こういう感じなんでしょうけど、
コレは一体、なんぞや?!(苦笑←重症)

(2)
//----------------------------

setcookie(session_name(), '', time()-42000, '/');
}

//----------------------------

>time()-42000

ここの「-42000」という値は、マイナス値であれば何でも良いんでしょうか?
42000という数字に何か意味はありますでしょうか。
マイナスの時間に設定することで、クッキーを削除する、
ということをしようとしているのかな、なんて思っていますが。

またしても、長い補足で、お手数をお掛けします。。^^;
投稿日時:2009/08/18 23:04

その他の回答 (全6件)

  • 回答No.7

ベストアンサー率 79% (381/480)

■セッションが引かれているかどうか
これの意図するところは、会員サイトなので、IDとパスなどの認証が通っているかどうかをチェックするという意味合いです。
<?php
session_start();
if(isset($_SESSION['user_id'])){
/*
例えば認証が通ってログインしたら、セッション変数にユーザのIDを格納しておくとか。セッション変数にuser_idがセットされてなければ、認証が通ってないということで、画面が遷移しないようにする。
*/
}
?>
ここらへんの実装は、ここで掘り下げなくても、理解されていますね。

■(2)と(3)の違い
COOKIEにセッションIDが残ってて、ブラウザがソレを通知してきたタイミングで、gc_maxlifetimeに到達はしているものの、GCが発動していなかった場合、ログイン後の遷移が行われてしまう可能性がありますので、プログラム側で、明示的にチェックしてやる必要があると思われます。

■セッションファイルと、その中の値であるセッション変数の関係
セッションファイルというのは、(ファイルベースの)データベースです。
実際に明示的に記述することはあまりないかもしれませんが、
http://php.nfsi.pt/manual/ja/function.session-write-close.php
session_write_closeという関数があり、セッションファイルに$_SESSION変数で保持した値を(セッションファイルに)書き込んで閉じます。これは、session_startをしていれば、スクリプト終了後に自動的に呼ばれるものです。
SQLなデータベースであれば、INSERT文やUPDATE文で行うようなことを、自動的にやってくれてるわけです。
で、session_destroyというのは、セッションを閉じるのではなくて削除します。DELETE文でテーブルやレコードを削除するのに近いですね。

■(A)の過程は、(B)をするのであれば、必要ない処理なのか
session_destroyしても、$_SESSION変数はunsetされるわけではないですので、session_destroy関数が叩かれた後も、$_SESSION変数に値が残ってますので、
$_SESSION = array();
として、リセットしたほうが良いかと思います。

■セッションが閉じられても、クッキーの有効期限が残っている場合
サーバ側にセッションが残ってないので、クッキーの有効期限が残っていても認証がされてしまうことはないと思いますが、ブラウザから無駄な通信が行われることもありますし、それ以外の何らかの予期せぬ出来事があるかも分かりませんので、削除したほうが良いのではないでしょうか。


大体のことが分かったら、後はオープンソースのログイン認証が行われるアプリケーションなどの実装を見てみるとノウハウ的な部分は分かると思います。
ECCUBE、WordPress、XOOPS、などなど。
他にも、
http://www.ideaxidea.com/archives/2007/11/phpphpuserclass.html
こちらで紹介されているようなユーザ認証部分だけのクラスライブラリなどもあったりします。
補足コメント
march4

お礼率 83% (628/754)

>■セッションが引かれているかどうか

理解しました!


>(2)

GCの、
セッションファイルの削除
に使われる確率の設定具合
によって、

有効期限を迎えているにも関わらず、
存在し続けているセッションファイルを、
チェックする必要があるわけですよね。

ここ、完璧に理解できたと思います^^


>(3)

で、これは、
セッション変数の中に格納する値でもってコントロールする、
セッションの有効期限、
という感じですかね。

セッションファイルの有効期限ではなく、
セッションファイルの中の1データに、
有効期限を意味するデータを格納している、
という感じで理解しました。

恐らく、ちゃんと理解できていると思います。笑

この(3)における、「有効期限」は、

(1)(2)とは異なり、その値は、一意的ですよね。

(1)は、書き換えられる可能性がある
(2)は、GC頼み
という意味で、それぞれ、一意的とは言い難いですから。


>セッションファイルというのは、(ファイルベースの)データベースです。

セッションファイルと、その中に書かれているデータは別物なんですよね。

セッションIDの名前にプレフィックスがくっついて、
セッションファイル名になり、

そのファイルの中のデータが、
セッション変数に格納した値であり、

そのセッションファイルとクライアントを
1対1対応で結びつける際に使う技術がクッキーで、

その対応関係を照合するのに、
$_COOKIE['セッション名']にて、セッションIDを呼び出す方法を取る、
ということなのですよね。

セッション関連の動的な構成要素は、

・セッションファイル名、
・セッションID、
・セッション名、
・セッション変数(連想配列)のインデックス値
・セッション変数(連想配列)の値

こんな感じでしょうか。
なんだか、すごく分かりにくい構造をしていたのですね。
最初から、セッションという概念はややこしいものだろうなと直感していたので、質問がかなり後回しになっていました。
(クラスより後になりました。)

おかげさまで、今、ようやく分かりつつあります。


>session_destroyしても、$_SESSION変数はunsetされるわけではない
>session_destroy関数が叩かれた後も、$_SESSION変数に値が残ってます
>リセットしたほうが良いかと

了解です。
では、(A)(B)(C)、
全てセットで、基本は、行っていこうと思います。


>サーバ側にセッションが残ってないので、クッキーの有効期限が残っていても認証がされてしまうことはないと思いますが、

えっと、
session_destroy()後、
セッションファイルは消されますよね、
ということは、セッションIDもなくなりますね、
なので、
クッキーがクライアントで生き続けていたとしても、
$_COOKIE['セッション名']で呼び出される値である、
セッションIDは、既に削除済みなわけですから、
そのクッキーは事実上、無効なものであるけれども、
クッキーそのものの存在自体はまだあるわけだから、
予測不能な振る舞いをする可能性があり、
それを断つ意味で、クッキーの有効期限も無くしてやった方が良い、というわけで、

クッキーの有効期限にマイナス値を設定し、
クッキーに消滅してもらうわけですね。

つながってきました!

>大体のことが分かったら、後はオープンソースのログイン認証が行われるアプリケーションなどの実装を見てみるとノウハウ的な部分は分かると思います。

ですね^^
分かる部分が多くなってきましたので、
それを呼び水に、さらに多くのことを吸収していけそうな気がしています。

セッションファイル蓄積による、サーバ圧迫が
どの程度、処理速度に悪影響をもたらすか等の、
より発展的なことがらについては、
おいおい調べていけたらと思います。

>ECCUBE、WordPress、XOOPS、などなど。

過去、XOOPSを使った経験があるので、
古巣に立ち返ってみます。笑

当時、プログラミングのプの字も知らなかったので、
XOOPSの中に組み込まれている数々のphpファイルを
私は全く理解することができませんでしたが、
今なら、きっと理解できるはずです!

>ユーザ認証部分だけのクラスライブラリなども

こちらも、じっくり読ませて頂きますね^^

ひとまず、セッションについては9割くらい理解できたものと思います。(強気 笑)

すべて、hogehoge78さんのおかげです。
いつも、ありがとうございます。
投稿日時:2009/08/21 04:54
  • 回答No.6

ベストアンサー率 79% (381/480)

■フローに関して
若干誤解があるようです。
記述するプログラム中でCookieを診断はしてません。
プログラムで判断するフローは、
・セッションが引かれているか

・引かれていた場合、セッション変数に値が残っているので値をチェック($_SESSION['time']のことです。私の書いたものはセッション変数が惹かれているかははしょってあります)

・セッションが引かれていないか、セッションの有効期限が過ぎている場合、ログアウト(またはログアウト画面へのリダイレクト)処理(上記セッションがそもそも引かれていない場合どうするかの診断もはしょってあります)

という流れです。有効期限について、
(1)Cookieというセッションとは別物のクライアントにのこるファイルの有効期限
(2)サーバにのこるセッションのファイルの有効期限
(3)プログラムで制御したいセッションというものの有効期限

と、有効期限は三種類あるわけですが、
(1)は書き換え可能なので、不正な有効期限のものが送りつけられてくる上に、PHP上でセッションを閉じても(session_destroy)してもCookieの有効期限が残っていればCookieは削除されないので、セッションを閉じる際に同時にCookieも強制的に削除する必要があります。
(2)これは、session_destroyするか、session.gc_maxlifetimeに到達して且つ、GC(ガベージコレクト)が発動した場合に削除されます。
http://monolog.spanstyle.com/2005/07/session.html
こちらにGCについて詳しく書いてありましたが、つまるところ、一定確率でGCが発動するので、GCが発動しなければ残っている可能性があるものです。
(3)そうすると(1)と(2)がプログラム中で、自分で意図した有効期限外でもログイン中としてプログラムが動いてしまう場合があります。
そこで、セッション変数にログイン日時を与えてやって、有効期限を確認し、有効期限外だったらプログラムから両方のファイルを削除してやる必要があります。
<?php
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(), '', time()-42000, '/');
}
session_destroy();
?>
ここの処理のくだりは既に「このセッションは有効でないからログアウトすることに決定」という判断がされた後の記述ですので、判断を行っている場所ではないです。単純にCookieとセッションを削除するための記述です。
if(isset($_COOKIE[session_name()]))
これは、$_COOKIE変数に、そのキーが存在するかの有無を単純にチェックしているだけです。存在していたら削除する、というだけで、それ以外に意図はないです。どうしても気になるのであれば、
<?php
setcookie(session_name(), '', time()-42000, '/');
session_destroy();
?>
とだけ記述しても削除されます。ただし、今後docomoのようにCookieを保存できない端末で利用するように環境を変更した場合、ログアウトの時に無駄な処理(Cookieが使えないのにsetcookieを行う)が発生しますね。
補足コメント
march4

お礼率 83% (628/754)

プログラムで判断するフローは、

>・セッションが引かれているか
>私の書いたものはセッション変数が惹かれているかははしょってあります

プログラムのフローの中には、
「セッションがひかれているか」を確認する処理は
書かれてはいないが、これは実際には必要で、
その処理は、ここでは「はしょられている」という理解でよろしいですか。

session_start();
が正常に宣言されているかどうか、
これが、つまり、セッションが引かれているかどうか、
と同じ意味なのですよね?

セッションを引く = session_start();

と私は解釈しています。

で、このsession_start();が、問題なく宣言できたかどうかを判定する処理が必要なわけですね。
(hogehoge78さんが書いて下さったソースの中では、はしょられている、ということですよね。)

この判定の仕方については、自分で調べますね!

>・セッションが引かれていないか、セッションの有効期限が過ぎている場合(、ログアウト)

if($max < time()){~(ログアウト処理)~
ということですよね。


/*----------------
有効期限について、

(1)「セッションとは別物」の「クライアントにのこるCookieというファイル」の有効期限

(2)サーバにのこる、セッションファイルの有効期限

(3)プログラムで制御したいセッションというものの有効期限
----------------*/

>と、有効期限は三種類あるわけですが、

(2)と(3)の違いが、私の中で明確ではありませんでした。
そして、現在も、若干、混同しています。苦笑
おかげさまで、(1)はOK。


>(1)はPHP上でセッションを閉じても(session_destroy)しても Cookieの有効期限が残っていればCookieは削除されないので

フローを再確認
----------------★★★-------------------------
・session_start();
・セッションファイルがランダム名でサーバ側に作成されます。
・その中に適宜、セッション変数のデータが入れられます。
・そのデータ(あれ?!データではなく、セッションファイルと、かな?!)と1対1対応で結びついている照合証のようなものが、クライアント側に渡されているクッキーファイルのクッキー値です。
・セッションを閉じるとは、サーバ側に置かれているセッションファイルを削除することです。

/*
セッションファイルと、その中の値であるセッション変数?
の関係がよく分かっていない気がします!汗
*/
//-------↓ by 某サイト ↓------
・ただし、セッションファイルを削除しても、メモリ内には、セッション変数とその値が残っているので、これを削除してから、session_destroy()する必要があります。
よって、

$_SESSION = array();
session_destroy();

のような方法で処理する方が良い。

(私が誤解していたら、爆死です。)

//------↑ by 某サイト ↑------

で、

>Cookieの有効期限が残っていればCookieは削除されないので、

setcookie(session_name(), '', time()-42000, '/');

にて、クッキーも削除する必要がある、と。

つまり、

セッションを閉じる場合には、その下準備がいくつか必要なのでしょうか?

(A)まず、メモリ内のセッション変数とその格納値をarray()等で削除
(B)次に、クッキーファイルの有効期限をマイナス化
(C)ようやく、session_destroy();

(A)の過程は、(B)をするのであれば、必要ない処理でしょうか?

それと、
「セッションが閉じられても、クッキーの有効期限が残っている場合」とは、どんな場合なのでしょう。

閉じたはずのセッションが、また使われてしまいかねない状況なのでしょうか?

/*
分からないことだらけで、すみません。
でも、ようやく核心部分に辿り着けたような気がしています。
*/

----------------★★★-------------------------


>(2)これは、session_destroyするか、session.gc_maxlifetimeに到達して且つ、GC(ガベージコレクト)が発動した場合に削除されます。
http://monolog.spanstyle.com/2005/07/session.html

実は、このサイトを予め読んだ上で、本質問をしたのでした。笑
なので、その内容については、概ね理解できているものと思って頂いて結構です。

>ここの処理のくだりは~(中略)~それ以外に意図はないです。

こういった、プログラムの背景について説明頂けると、とても分かりやすいですね^^
助かります。

>ただし、今後docomoのようにCookieを保存できない端末で~(中略)~無駄な処理が発生しますね。

ここも同様に助かります。
if文を挟むことで、プログラムの汎用性が高まるわけですね。
投稿日時:2009/08/20 23:35
  • 回答No.5

ベストアンサー率 79% (381/480)

■PHPが自動的に保存するテキストファイルの名前について
実際は先頭にプレフィックスが付きますが、そこは特に突っ込んで考えなくても良いところですね。
どうしても気になるのであれば、セッションを利用するアプリケーションを走らせて、php.iniで設定されているディレクトリを眺めてみると良いと思います。権限がないなら、見れませんが、自宅PCにでもローカル環境を作って置くと良いかもしれませんね(windowsであればxamppとか)

■シリアライズについて
シリアライズは、PHPの標準関数「serialize」相当のものです。
JavascriptでいうところのJSON形式に似たような感じです。

■クッキー単体でクッキーを使う場合というのは、どんな時なのか
検索サイトや、何らかのアクセス解析とかで、リピーターをカウントするとかでしょうか。後は、あまり重要でない情報、簡単なCGIゲームのようなものとかFlashのゲームとかで、セーブデータをCookieに保存しておくとか。

■なぜCookieの有効期限を設定するか
前回回答の通り、デフォルトではブラウザを終了すると共に、Cookieは削除されます。そうすると、有効期限内であっても、ブラウザはCookieに保存してあったセッションID情報を破棄しており、ログイン情報を維持できません。それでは今回ご質問の要件仕様に満たないためです。
補足コメント
march4

お礼率 83% (628/754)

>実際は先頭にプレフィックスが付きますが

確かに、そんな感じなのだろうと思っていました。^^

>シリアライズは、PHPの標準関数「serialize」相当のもの

「serialize」について、PHPマニュアルの例を見てきました。
見た感じ、暗号化されたような数字列?に変換されるような、
そんな印象を受けました。

>■クッキー単体でクッキーを使う場合というのは、どんな時なのか

大変、分かりやすくまとめられており、とても参考になりました。^^

>■なぜCookieの有効期限を設定するか
>ブラウザはCookieに保存してあったセッションID情報を破棄しており、ログイン情報を維持できません。

ここは理解できました。問題なさそうです。

えっとですね、

セッションを使う関係上、同時にクッキーも使うことになるために、
そのセッションを生かすために、ブラウザ終了と同時にクッキーに死なれないように、クッキーにライフタイムを与えるわけですよね。

で、私が気になったのは、
「次回アクセス」時に、有効期限かどうかの判断を
まず、クッキーファイル内に記載されている有効期限からチェックをしますよね?
そして、OKならば、今度は、
セッション変数に格納されている有効期限と照合するわけですよね。

この一連の精査の中で、
書き換えられている可能性のある、

いわば、

信頼性の低いクッキーファイル内の有効期限

をなぜ最初にチェックする必要があるのかなと、感じたわけです。

あれ、なんか変なこと言ってそうですか?苦笑

「次回アクセス」時のチェックフローを書いてみます。

チェック(1)
セッション名を使った方法(if (isset($_COOKIE[session_name()])) のことです。)にて、クッキーファイルの有無をチェック。
あれば次へ進む。
なければ、クッキーファイルを送りつける。

チェック(2)
クッキーファイルがあった場合、その有効期限をファイル内を調べることでチェック。
(書き換えられているかもしれないが、)有効期限内かどうかチェック。
期限内であれば、次へ。期限外であれば、クッキーファイルを送りつける。

チェック(3)
クッキーが有効期限内ではあったが、書き換えられているかもしれないので、
セッション変数に格納した有効期限も使って、さらなるチェックを行う。
もし有効期限内ならば、晴れて、
「おまえは、もうログインしている…。」という状態へ。
もし有効期限外であれば、
「おまえは、クッキー改ざん野郎だ、許せない!新しいクッキー食え!」
と、説教部屋へ。

こんな感じでしょうか。
で、何が言いたいかと言うと、

チェック(1)(2)をすっ飛ばして、チェック(3)から
チェックは始められないものなのかな、、、と。。。

チェック(1)、(2)って、必要なのでしょうか?笑
(3)ひとつで、事足りるような気がしています。

変なことを言ってそうなのを承知で質問しています。苦笑
どうぞよろしくお願い致します。
投稿日時:2009/08/20 02:01
  • 回答No.4

ベストアンサー率 79% (381/480)

■session_set_cookie_params()関数とsetcookie()関数の違い
PHPの挙動として、
session_start();と関数をたたきますとセッションがスタートします。
セッションがスタートするとはどういうことかといえば、
前回の回答に記述したとおり、ランダムでユニークなIDを生成するわけですが、
そのユニークなIDの文字列の名前が付いたテキストファイルを、php.iniで設定した
テンポラリディレクトリに保存します。

そのテキストファイルの中には何が格納されるかといえば、session_start後に利用できる
スーパーグローバル変数「$_SESSON」に格納された値(をserializeしたもの)が格納されます。

そして、PHPスクリプトが終了するタイミング(というかスクリプトがWebブラウザにHTTPヘッダを送信する際)で
Set-Cookieというヘッダを送出します。
これにはCookieの名前が(デフォルトの場合)PHPSESSIDという名前で、格納値が上記のランダムでユニークな値が付加されます。
そのようなヘッダをWebブラウザが受け取ると、WebブラウザはCookieファイルに書き込みます。

次回、セッションがスタートしているファイルにアクセスするたびに、Webブラウザが格納したCookieの内容を
PHPスクリプトに送信してきます。
Cookieの内容とは、PHPSESSID={上記で生成したID}となりまして、
PHP側では、スーパーグローバル変数$_COOKIE['PHPSESSID'];で参照できます。

この一連の流れでは、PHPのセッション機構が自動的にCookieに値をセットしてしまうので、setcookie関数の使いどころがないですね。
すなわち、Cookieの有効期限が設定できず、デフォルトの「ブラウザが閉じたときにCookieを削除する」ということになってしまいます。
そこで、session_startを叩く前にsession_set_cookie_params()で有効期限やセキュリティ用の設定値を付加してやるわけです。

PHPのセッションが必要なく、ただCookieにデータを格納するだけであれば、setcookieを使う、ということですね。

■Cookieの書き換えに関して
ここで、
>ただ、cookieはクライアント側にファイルとして記録されておりますので、
>ユーザが書き直す場合が当然あります。
といったのは、「IDを書き換える」、ということではなくて、「有効期限」の書き換えにフォーカスしたもので、
Cookieで有効期限を設定しても、ユーザが自分のPCに保存されているCookieファイルを開き、メモ帳なり任意テキストエディタで
有効期限を修正したら、永続的に有効となってしまいます。
Cookieファイルの書式は
http://d.hatena.ne.jp/RIP/20070323
こちらが参考になります。
その為、サーバに保存されたセッションのテキストファイル内に、そのセッションIDが生成した日付を記録しておき
Cookieで設定した有効期限だけではなく、セッションIDにも有効期限のチェック処理を設ける必要があります。
ソレがサンプルスクリプトの部分です。

■気になるソース
(1)$_COOKIE[session_name()]
結局のところ上記で説明させていただいたとおり、セッションを扱うに当たって、クライアント(顧客PC側)に何らかの情報を
格納する必要があり、HTTPの仕様上、Cookieしか保存するすべがないので、
Cookieを「利用することにした」というものなので、
Cookieファイルの名前とその値の組み合わせが、
PHPSESSID={上記で生成したID}
となっており、ソレをPHPの親切設計により、
$_COOKIEから簡単に参照できますよ、というところですね。
setcookie関数で、任意の名前=任意の値
というものをセットした場合は、
$_COOKIE['任意の名前'] == '任意の値'
となります。

(2)time()-42000に関して
「マイナスの時間を設定することでクッキーを削除する」の理解でよいです。
私もPHPマニュアルのコメントで記述されていたものを鵜呑みにして記述しているので、
由来は調べていません。すみません。
とりあえず、Cookieを削除する手法として、マイナスの時間を設定するというものがあるということです。

以上です。
補足コメント
march4

お礼率 83% (628/754)

例えば、
PHPSESSID=fec87ba5devfc80d2210db8891ac530a
で言えば、
「ユニークなIDの文字列の名前が付いたテキストファイル」とは、
「fec87ba5devfc80d2210db8891ac530a」という名前になりますでしょうか。

セッションの構成を大雑把に言うと、
・セッション名
・セッションID
・セッション(変数)の中身
こんな感じでしょうか?(★ポイント)

>そのテキストファイルの中には何が格納されるかといえば、session_start後に利用できる
スーパーグローバル変数「$_SESSON」に格納された値(をserializeしたもの)

「serializeしたもの」…。
例えば、
<?php
session_start();
$_SESSON['example'] = '例えば';
?>
で、セッションに格納した「例えば」という文字列を、そのままのカタチで保存するのではなく、
シリアライズして(何らかの文字変換を行って)保存する、ということですよね。

(整理)
・session_start(); にて、セッションをスタート。
・ユニークなID(例えば、「fec87ba5devfc80d2210db8891ac530a」のような)が生成される
・と同時に、「fec87ba5devfc80d2210db8891ac530a」というファイル名のテキストファイルが、
テンポラリディレクトリに保存される。

次に、
$_SESSON['example'] = '例えば';
という、セッション変数に値を格納するような処理をすると、

・そのテキストファイルの中身に、「例えば」という文字列そのものではなく、「シリアライ
ズされた『例えば』という文字データ」が入れられる。

こんな感じでしょうか。


>この一連の流れでは、PHPのセッション機構が自動的にCookieに値をセットしてしまうので、setcook
ie関数の使いどころがないですね。

「PHPスクリプトが終了するタイミングでSet-Cookieというヘッダを送出」
ここで、setcookie関数のようなことがされているわけですね?(★ポイント)


>すなわち、Cookieの有効期限が設定できず、デフォルトの「ブラウザが閉じたときにCookieを削除す
る」ということになってしまいます。

おおーー。(何かがつながった瞬間)
だから、私は、
「クッキーの有効期限の設定についてはなんとなく分かりそうなんだけど、セッションの有効期限って??」
と思っていたのかもしれません。

>そこで、session_startを叩く前にsession_set_cookie_params()で
>有効期限やセキュリティ用の設定値を付加してやるわけです。

ほぉほぉ。なるほどー!
クッキーにおいては、setcookie()によってクッキーの有効期限を設定しますが、
このような「有効期限を設定する処理」をセッションにおいてする場合には、
session_set_cookie_params()で行う、
ということなのでしょうね。(ポイント★)

>PHPのセッションが必要なく、ただCookieにデータを格納するだけであれば、setcookieを使う、とい
うことですね。

セッションを使用する際、主にクッキーを利用するということは理解できましたが、

クッキー単体でクッキーを使う場合というのは、どんな時なのでしょう。
書き換えられてもいいですよ、というくらいの軽~い気持ちで、
クライアントに情報を渡しておくなんて場合でしょうか。

回答NO.2さんの、
「$_COOKIEと$_SESSIONのどちらでもいいなら、phpなら$_SESSION使いましょう。」
というのは、そういう意味だったのでしょうかね。

■Cookieの書き換えに関して
>「IDを書き換える」、ということではなくて、「有効期限」の書き換えにフォーカス
>メモ帳なり任意テキストエディタで有効期限を修正したら

クッキーだけでログイン有効期限を判断するのは、
少々、荒っぽいやり方だということが分かりました。

>その為、サーバに保存されたセッションのテキストファイル内に、そのセッションIDが生成した日付を記録しておき
>Cookieで設定した有効期限だけではなく、セッションIDにも有効期限のチェック処理を設ける必要があります。

なるほど、、、(←若干つながってないw)

つまり、クッキーだけでは不安が残るので、セッションでもチェックしましょう、と。
ならば、セッションだけで良いのでは。。。?と思えてしまうのですが…

「(前回の回答より抜粋)セッション変数に、ログインされた時間を記録」
という方法にて、訪問者のログイン状態の有効期限を設定しているのは、
これは、クッキーファイルの有効期限とは全く別経路の話なわけですよね。

セッションの中で使用されるクッキーの有効期限と、
セッション変数の値(セッションの中身)として入れた「time()等を使用したログイン有効期限」は、まったく別の仕組みであって、
両者は異なる仕組みであるからこそ、2重のチェックになり得るわけですよね。(★ポイント)
投稿日時:2009/08/19 16:23
お礼コメント
march4

お礼率 83% (628/754)

最初のアクセス

・セッション利用開始。同時に、クッキーの利用も開始。

・クッキーファイルがクライアントに送られ、一応、ファイルには有効期限を設定しておきます。
 ただし、クッキーファイル内のデータは書き換えられる可能性あり。

・セッションでは、セッション変数に有効期限を格納することを行い、サーバ側に保存。
 このデータは、ちょっとやそっとじゃ書き換えられたりしない。

次回アクセス

・クッキーによる有効期限のチェック

↓(書き換えられている可能性があるので、)

・セッションによっても有効期限のチェック
---

セッションを使う際に、おまけで付いてくるようなクッキーファイルの有効期限。
初めから、これを信用せず、セッション変数によって設定した有効期限でもって、
訪問者のログイン状態をチェックするのであれば、
クッキーファイルの有効期限でチェックをする意味とは?(★ポイント)

セッションとクッキーがややごっちゃに…
ちょっと整理します

セッションは大雑把に言うと、
・セッション名:例/PHPSESSID(どちらかというと、固定的な値)
・セッションID:例/fec87ba5devfc80d2210db8891ac530a(ぽんぽん生成される感じ)
・セッションの中身:例/'例えば'(人間が任意に格納する情報、のみ?)

一方、クッキーは、
・クッキー名:例/PHPSESSID
(人間が任意に決める固定的ではない値。セッションを利用している時の、セッションIDを受け取る際には、クッキー名にセッション名を入れて扱う。)
 →例えば、$_COOKIE['PHPSESSID'] または、$_COOKIE[session_name()] といった書き方になる。

・クッキー値:例/fec87ba5devfc80d2210db8891ac530a
(同様に任意の値。やりとりの際には、クッキー名とセットで渡される(渡された)値のことで、
クッキー名にセッション名を入れた場合のクッキー値はセッションIDになる。)

・クッキー情報?:クッキーの有効期限、有効範囲などの情報

散らかった内容のまま返事をしてしまっていることをお許し下さい。
投稿日時:2009/08/19 16:32
  • 回答No.2

ベストアンサー率 50% (6/12)

$_COOKIEと$_SESSIONのどちらでもいいなら、phpなら$_SESSION使いましょう。
ふつうにセッションの期限設定するなら、session_cache_limiter 使うんじゃないでしょうか。ini_setは使えない場合もありますし。
お礼コメント
march4

お礼率 83% (628/754)

>$_COOKIEと$_SESSIONのどちらでもいいなら、phpなら$_SESSION使いましょう。

わかりました。
ちなみに、PHPにおいて、$_COOKIEじゃないとまずい場合というのはあるのでしょうか?

>ふつうにセッションの期限設定するなら、session_cache_limiter 使うんじゃないでしょうか。

session_cache_limiterについて、調べてみました。
が、よくわかりませんでした。
session_cache_limiterで、具体的な期限設定ができるのでしょうか?
例えば、24時間という時間を設定するなんて場合に、
session_cache_limiterは使えますか?
ざっと調べた感じでは、使えるようには思えなかったのですが…。
投稿日時:2009/08/17 13:54
  • 回答No.1
>この$_SESSION['login']値を保持している間、訪問者は、
>サイト内のページを、ログインされた状態として閲覧できる
>と、私は考えています。

というより、「この値を保持している間、ログインされた状態として閲覧できるように作る」ということ。つまり、$_SESSION['login']の値をチェックし、そこに正しく値が保管されていればログインされているとみなす、というように自分でプログラムを作る、ということ。$_SESSIONというのは、あくまで「特定のクライアントに特定の値を保管するための機能」でしかなく、それをどう利用するかはプログラマ次第。だから、そう作れば、そう動く。

>ini_set("session.gc_maxlifetime", "~仮に24時間としておきます~");
>という記述は、
>そのスクリプトでセッションIDをクライアントに与える場合の「そのセッションIDの保持期間」のみ
>を設定できる、という理解でよろしいでしょうか。

これは、「全部のセッションがそうなるのか、それともこのスクリプトで作成したセッションだけがそう設定されるのか」という意味だろうか。ならば、そう考えていい(このセッションだけが適用される)と思う。ただし、これはsession_startをする前に変更しておく必要がある。でないと正しく設定は反映されなかったはずので注意。

また、このgc_maxlifetimeというのはガベージコレクションの設定であって、ガベージコレクションが起動した際に、ここで設定された期限が切れているセッションを回収し破棄するということ。従って、「ここで設定した期限が過ぎたら、次のガベージコレクションで値は消される」ということであって、指定した時間でかっきりセッションが消えるわけではない。まぁ「最短で、この時間が経過すると消える」と考えるといいと思う。
お礼コメント
march4

お礼率 83% (628/754)

>というように自分でプログラムを作る、ということ。

はい、書き方が良くなかったかもしれませんが、
そのように考えて書いておりました。
なので、セッションを用いたログイン管理の考え方の大枠については、
logger_manさんと同じように考えている、と解釈して頂いて結構です。

>これは、「全部のセッションがそうなるのか、それともこのスクリプトで作成したセッションだけがそう設定されるのか」という意味だろうか。

はい、その解釈で問題ありません。

>ただし、これはsession_startをする前に変更しておく必要がある。

注意しておきます。

>このgc_maxlifetimeというのはガベージコレクションの設定であって

使用期限の切れたセッションに対し、削除処理を行うという作業を、
毎回のようにサーバにさせるのでは、処理速度に悪影響を及ぼすので、
あらかじめ、その削除処理をする確率を決めておき、
それに従って、「削除すべきものは削除する」ということを行う、
ということなので、

>「最短で、この時間が経過すると消える」と考えるといいと思う。

というご助言なのだと思います。

で、気になったのが、
また戻りますが、

>このgc_maxlifetimeというのはガベージコレクションの設定であって

という所です。

クッキー($_COOKIES)を使用する場合は、
setcookie()関数で、クッキーの保持期限を設定できますが、
セッション($_SESSION)を使用する場合の使用期限は、
どう設定するのでしょうか?
私は、その設定に使用するものが、
この、ini_set("session.gc_maxlifetime", "~仮に24時間としておきます~");
である(これしか方法がない)と思っているのですが、
何か間違っていますでしょうか。
またよろしければ教えて下さい。
投稿日時:2009/08/17 10:52
関連するQ&A

その他の関連するQ&Aをキーワードで探す

ピックアップ

ページ先頭へ