Webアプリケーションにおけるセッションとは、「ユーザーのアクセスに対してユーザー毎に変数を保持する」、「複数のページ間で、変数の共有を可能にする」とあります。Webサイトを訪れた訪問者が行う一連の行動や、その行動を通じてやり取りされる情報などがセッションにあたります。
PHPでは、セッションを理解することが重要なポイントになるので、ここではセッション管理の仕組みを分かりやすく解説していきます。
クッキーの章でも解説しましたが、Webデータのやり取りには、HTTPプロトコルというWebブラウザとWebサーバ間で交わされるインターネットプロトコルが使用されています。HTTPプロトコルには、状態を保持する機能がなく、ユーザー(ブラウザ)が連続的に複数回のアクセス(Webページの表示)をしても、サーバ側はそれを特定のユーザーの連続したアクセスと認識せず、複数のユーザーが複数回アクセスしたものとして認識します。
そこで、Webサイトに、特定のユーザーからの状態(アクセス履歴や、入力したデータなどの情報)を保持した上で、次にそのユーザーがアクセスしたときに、特定のユーザーからのアクセスであることをサーバ側が認識できるような機能を持たせるようにします。これをセッション管理といいます。
まず、ユーザーを特定するための仕組みとして、通常は初回アクセス時のユーザー対して、サーバ側からユーザーに対して自動的に識別コードを割り振り、その識別コードを使用してユーザーを特定します。この識別コードのことをセッションIDといいます。
ユーザー(ブラウザ)は、そのWebサイトにアクセスする度に、毎回必ずセッションIDを送信する必要があります。セッションIDは、※通常クッキーとしてブラウザに記憶され、Webサイトにアクセスするときにはブラウザが自動的に送信してくれます。セッションIDを使用してユーザーを識別できるようになれば、そのセッションIDをキーにして、サーバー側で情報を保存する場所を用意します。
セッションの仕組み
※
すべての環境でクッキーが使用可能なわけではありません。例えば携帯端末やブラウザでも、クッキーを無効にしているときはクッキーにセッションIDはセットされません。
このような場合には、URLの一部にセッションIDを埋め込む方法があります。セッションIDを含むURLでサーバにアクセスすることで、サーバ側でセッションを識別することができます。
通常、変数は複数のページ間で共有できません。また、ページのリロードによってもリセットされてしまいます。しかし、ここでいう変数はセッションを利用する事で、複数ページ間での共有や、複数回のリロードでも保持することができます。このような変数をセッション変数と呼びます。
具体的に、Webのショッピングサイトを例にすると、ユーザーは「商品の選択」「他の商品を検索」「選択した商品の取り消し」など、サイト内のページをいろいろ移動したあと、「レジ(精算画面)」に移ります。このときに、どの商品を選択したかの情報をどこかに蓄積しておかないと、レジで金額計算ができなくなってしまいます。そこで、選択された商品などをセッション情報としてセットしておき、ユーザーがサイトに滞在している間は保持しておくような仕組みが必要になります。
ショッピングサイトで必要な情報には、「ユーザーは誰か」「何と何をいくつ買ったか」などがあります。そして、このことを判断するためにセッションIDとセッション変数があるのです。「ユーザーは誰か」というユーザーの識別にはセッションIDが、「何と何をいくつ買ったか」という購入商品などの情報にはセッション変数がそれぞれ用いられます。
おおまかなセッション管理の仕組みがわかったところで、簡単にセッションを含むスクリプトを記述してみます。
PHPのセッション管理
<?php session_start(); if( isset( $_SESSION[ "count" ] ) ) { $_SESSION[ "count" ]++; } else { $_SESSION[ "count" ] = 1; } ?> <html> <body> あなたは <?php echo htmlspecialchars( $_SESSION[ "count" ] ) ?> 回目の訪問です <a href="<?php echo htmlspecialchars( $_SERVER[ "PHP_SELF" ] ) ?>">ページを更新する</a> </body> </html>
実行結果
あなたは 1 回目の訪問です ページを更新する上記のスクリプトでは、まずセッションをスタートさせるsession_start()関数を呼び出します。session_start()関数は、通常、セッション対象ファイルの先頭で呼び出す必要があります。
そして、「count」という名前の変数を、セッション間でのセッション変数名として登録します。セッション変数に入れた値は、PHPのプログラムが終わる際、サーバー内に自動的に保存されます。
「ページの更新」には、指定したリンク先に移動させるリンクタグを使用して、リンク先には、自分自身のファイル(パス)を表す※$_SERVER["PHP_SELF"]を指定しています。これにより、「ページの更新」をクリックすると再度上記のスクリプトが読み込まれ、2回目以降のアクセスの際には、session_start()関数がサーバー内に保存されたデータを元に、$_SESSION変数の復元を行います。
一度目のアクセス時には、「あなたは 1 回目の訪問です ページの更新」が、二度目のアクセス時には「あなたは 2 回目の訪問です ページの更新 」と表示されます。
※$_SERVER[ "PHP_SELF" ]
現在実行しているスクリプトのファイル名を意味し、「http://php.xenophy.com/index.php」であれば「/index.php」が返されます。
補足ですが、「htmlspecialchars( $_SESSION[ "count" ] ) 」の「htmlspecialchars」は、HTMLにおいて特殊な意味を持つ文字を、そのまま表示できるようHTMLの表示形式に変換します。以下に変換対象となる文字を一部記載します。
htmspecialchars()関数で変換対象となる文字列
変換される文字 | 変換された後の文字 | 内容 |
---|---|---|
& | &amp; | 常時変換される |
< | &lt; | 常時変換される |
> | &lt; | 常時変換される |
" | &quot; | quote_styleの設定による。デフォルトでは変換される。 |
' | &#039; | quote_styleの設定による。デフォルトでは変換されない。 |
セッション管理において、特定のユーザーを識別するために、サーバ側から割り当てられる識別コードを、セッションIDといいます。それでは、サーバ側から割り振られるセッションIDとは、具体的にどのようなものなのでしょうか。
セッションIDの文字列
id67934741a80ab0ab9248569eb9492acc上記のように、セッションIDには一見すると意味不明な文字列が割り振られます。
基本的に、セッションIDは第3者に推測されるような内容であってはいけません。セッションIDが推測されてしまうと、第3者が誰かのセッションIDを利用して、あたかもそのセッションIDが割り振られた本人としてアクセスできてしまいます。
そうなると、第3者が他人の個人情報を盗み見ることや、書き換えることができ、あるいはその人の権限で何らかの処理を実行できてしまうかもしれません。
この他人になりすますような不正アクセスを防ぐために、サーバでは上記のようなランダムな文字列が生成されて割り当てられます。
クッキーでセッションIDを保存する場合には、※標準ではサーバ上の「tmp」というディレクトリに「sess_id67934741a80ab0ab9248569eb9492acc」のようなファイル名で保存されます(ここではxampp下のtmpフォルダに保存しています)。
「tmp」ディレクトリ
「tmp」ディレクトリに作成されたクッキーの中身(ファイル)
session_name( name );
session_name()関数を使用して、現在のセッション名を取得、または設定することができます。セッション名は、セッションIDを受け渡すためのクッキー名やURLパラメータ名などに利用します。
セッションを開始した際に、クライアントのクッキー名として「PHPSESSID」を利用することが、「php.ini」のデフォルト値で設定されています。「php.ini」を直接変更することでも、デフォルト値の変更ができます。
実際に、session_name()関数を使用して、現在のセッション名を取得してみます。
現在のセッション名を取得する
<?php session_start(); session_name(); echo "現在のセッション名は ". session_name() ." です。"; ?>
実行結果
現在のセッション名は PHPSESSID です。session_name()関数を引数無しで使用すると、現在のセッション名が取得できます。
そして、引数を指定した場合は、現在のセッション名が変更されます。
なお、セッション名を変更する際、session_start()関数よりも前に呼び出す必要があり、かつセッション名は英数字のみ(数字のみは不可)で構成されている必要があります。
現在のセッション名を変更する
<?php session_name( "newsession" ); session_start(); echo "現在のセッション名は ". session_name() ." です。"; ?>
実行結果
現在のセッション名は newsession です。session_id( string id );
session_id()関数を使用して、現在のセッションIDを取得、または設定することができます。
session_id()関数を引数無しで使用すると、現在のセッションIDが取得できます。※引数を指定した場合は、現在のセッションID名が変更されます。
セッションID名を変更する際、session_start()関数よりも前に呼び出す必要があり、かつセッションID名は、「a-z」「 A-Z」「 0-9」で構成されている必要があります。
※
セッション保持にクッキーを使用している場合は、session_id()関数の引数を指定すると、現在のセッションIDと、引数でセットされるセッションIDとがまったく同一であるかどうかに関わらず、session_start()が呼び出される際、常に新しいクッキーが送信されます。
セッションIDの表示と変更
<?php session_start(); echo session_id(); echo "->"; session_id( "a0b1c2d3e4" ); echo session_id(); ?>
実行結果
18924741a20ab2ab2108577ab9492aba->a0b1c2d3e4上記のスクリプトのように、自動的に取得するセッションIDを任意の文字列に変更することができます。ただし、第3者が簡単に推測できてしまうセッションID名に変更すると、他人にセッションを乗っ取られるといった可能性があります。
そこで、セッションIDを絶えず変更させることのできるsession_regenerate_id()関数を使用してセッションIDの推測を防ぎ、セキュリティを向上させるといったことができます。
なお、セッションID変更後も、現在のセッション情報はしっかり維持されます。
session_regenerate_id( [ bool delete_old_session ] )
session_regenerate_id()関数は、現在使用しているセッションを終了させることなく、セッションIDだけを新しい値に置き換えます。
PHP5.1以降になってからは、セッションID変更後、古いセッション情報を同時に削除することが、引数の指定でできるようになりました。古いセッション情報を残しておくことはセキュリティ的にもよくありません。引数の「delete_old_session」をTRUEに指定することで、古いセッションを削除することができます。
セッションIDの自動変更
<?php session_start(); $old_id = session_id(); session_regenerate_id(); $new_id = session_id(); echo "変更前のセッションIDは ". $old_id ." です。‹br /›¥n"; echo "今現在のセッションIDは ".$new_id ." です。"; ?>
実行結果
変更前のセッションIDは 18924741a20ab2ab2108577ab9492aba です。ブラウザの再読み込みを行うと、下記のようにセッションIDが随時変更されていくことが確認できます。
ブラウザの再読み込み
変更前のセッションIDは 52fc5ca1b96555745795cde0cd956d25 です。ブラウザの再読み込み
変更前のセッションIDは 24d207e1965151916f0cdfaa6b3dfa6d です。session_save_path()関数を使用して、現在のセッション用のデータが保存されているディレクトリのパスを取得、または保存先ディレクトリを変更することができます。
session_save_path()関数を引数無しで使用すると、現在の保存先ディレクトリまでのパスが取得できます。引数を指定した場合は、指定したパスが保存先となります。
なお、保存先を変更する際、session_start()関数よりも前に呼び出す必要があります
セッションデータの保存先ディレクトリを変更する
<?php session_save_path( "/temp" ); session_start(); echo "現在のセッションデータは". session_save_path() ."に保存されています。"; ?>
実行結果
現在のセッションデータは/tempに保存されています。session_save_path()関数を使用して、現在のセッション用のデータが保存されているディレクトリのパスを取得してみます。
セッションデータの保存先ディレクトリを確認する
<?php session_save_path( ); session_start(); echo "現在のセッションデータは". session_save_path() ."に保存されています。"; ?>
実行結果
現在のセッションデータはC:\xampp\tmpに保存されています。上記のスクリプトの「session_save_path( );」からセッションデータ保存先のパスがわかりました。