PHPまとめ - セッション管理

HOME | TOP

■ 概要

セッションは、アクセスしてきた人が次にアクセスした時も同一のマシン環境からかどうかを判別するための仕組みです。

セッションを開始する時には『セッションID』というものを発行します。
これはその場で生成したランダムな文字の並びなのでこの中に情報が盛り込まれているということはありません。
アクセスしてきたユーザとは何の関連性もないただのランダムな文字列を発行することは、セッションIDを他の情報から割り出されないようにするためには重要なことです。

発行したセッションIDは、一方はアクセスしてきた人のブラウザに保存してもらい、もう一方はサーバ側で持っておきます。
このブラウザ保存はクッキーと言われる仕組みを使っているのでブラウザがクッキーを受け入れない設定になっていればこの方法は使えないということになります。

ログイン認証の時には、ユーザ名とパスワードが一致すればセッションIDを発行してログイン状態となります。
そうなると認証以降は送られてきたセッションIDとサーバ側に保存されたセッションIDの合致を見てそこに結び付けられたユーザ名を見ることでユーザ判別ができるようになります。

セッションの流れ セッションID発行 認証

■ セッションの基本

▼ session_start()の2つの挙動

セッション開始を行うsession_start()には2つの挙動がある。

  1. セッションIDが送られてこなければセッションIDを発行してクッキー保存するように送り付ける。
  2. セッションIDが送られてきたら該当するセッション用ファイルを探してその中にデータがあればセッション配列$_SESSIONにセットする。


▼ セッションIDが送られてきたかどうやって判断しているか

session_name()の返す文字がセッションIDのキーになるので、例えばキーが"SID"なら$_COOKIE['SID'], $_POST['SID'], $_GET['SID']のどれかが送られてきたかを見ていることになる。つまり$_REQUEST['SID']一つを見てるのと同じ




▼ 架空のセッションIDを送るとどうなるか

サーバ側が受け取ったセッションIDに該当するファイルを探しに行って、該当ファイルがないということになるとその架空のセッションIDに基づいてファイルが作成されてしまう。この挙動を知らないととんでもないセキュリティホールを作ってしまいかねないので注意。




▼ 架空のセッションIDを弾くには

session_start()が実行される前の段階で、送られてきたセッションIDが正当なものかチェックする必要がある。

具体的に「セッションIDに該当するファイルが存在する」かチェックするには以下のコードになる。

もちろん架空のセッションIDを弾く以外にもチェック項目はあります。

まず肝心なことは、認証をクリアしたらセッション変数にユーザ名を残すことで、次回からのアクセスでユーザ判別できるようにする。

アクセスの途中でホスト名が変わったら弾くようにしたければこれもセッション変数にセットしておいて、アクセスの度にチェックすればよい。

アクセスの度にホスト名が変わる携帯などもあるのでこれだと実践的ではない。


■ session_start()コール前と後

session_start()を実行する前の段階でできること(使用できる関数など)と後の段階でできることに分けて考える。

▼ session_start()コール前


▼ session_start()コール後

session_destroy()によるセッション関係の破棄では、セッションファイルの削除のみで、セッション変数の値がメモリ上に残っていてもなにもしないし、保存されたクッキーに対してもなにも行わない。


■ セッションハイジャック

セッションIDを他人に入手されてしまった場合、例え有効期限を設定していても期限内であれば不正利用される可能性があります。

こういう場合の対策として、アクセスする度にセッションIDを更新するいわゆるワンタイムセッションという方法があります。

方法はsession_regenerate_id()関数を使えばいいわけですが、この関数はバージョンによって挙動が違うのである程度バージョンの違いを吸収する方法を考えてみます。


■ 認証スクリプト

試しになにか作ってみましょう、ということで認証を行ってセッションを張るスクリプトを

[inc_login.php]

使い方は簡単、認証をかけたいスクリプトからこのinc_login.phpを呼び出します。

まだセッションが張られてなければログイン画面を表示します。

パスワードはMD5ハッシュ化したものを設定するようにしています。



[foo.php]

特別にグローバル変数「$id」にはログイン時ユーザ名を、もしクッキー受け入れ拒否なら「$hidden」にはセッションID値入りのhiddenタグを、「$param」にはセッションID値入りのリクエストパラメータをセットして呼び出し元スクリプト側でも利用できるようにしています。


2010(C)Mingw