仕事で使える魔法のLAMP
第43回 PHPでセッションを利用するための設定
株式会社イメージズ・アンド・ワーズ
代表取締役
山口晴広(やまぐち はるひろ)
2012/2/23
| 今回は、ちょっと大きなWebアプリケーションを作ることになると、必要になる「セッション」の機能をPHPで利用する方法を解説します。さらに、これまで説明しきれなかったけど、設定しておいたほうがよい項目についても解説します(編集部) |
別々のHTTPアクセスの間でデータを共有させる
第37回より、PHPの実行時設定について解説を続けてきましたが、今回でPHPについての解説は最後です。PHPの設定ディレクティブはまだまだたくさんありますが、LAMP環境を構築するときに設定しておくべき内容はおおよそ網羅できたと思います。残りの設定ディレクティブは、PHPプログラムの開発というテーマに関係するものになります。
今回はセッションに関する設定について解説します。そして、PHPに関する設定の中でも、これまで紹介する機会を作れませんでしたが、設定しておいた方がよいものがいくつかありますので、これも取り上げます。
セッションについてはご存じの方も多いと思いますが、軽く説明しておきます。セッションとは、簡単に言うと、同じブラウザからの一連のHTTP(HyperText Transfer Protocol)アクセスの間で、データを共有するための仕組みです。
HTTPのアクセスは1つ1つ独立していて、それぞれのアクセス同士には何の関係もありません。しかし、例えばログインをするようなシステムでは、そのシステムへ接続してくるHTTPアクセスのそれぞれにログイン中であることを認識させなければなりません。HTTPというプロトコルの仕組みだけではこのようなことはできません。
そこでセッションを使うと、Webブラウザから実行される複数のHTTPアクセスと、ログイン中のユーザーとを関連付けることができるようになります。この関連付けには、クッキーを利用します。クッキーにセッションIDと呼ぶ識別情報を保存することで実現するのです(図1)。
![]() |
| 図1 セッションの処理の流れ |
PHPは、sessionエクステンションでセッションに対応しています。このエクステンションは、標準で有効になっています。$_SESSIONという配列変数に値を保存することで、セッションにデータを保存することが可能になります。
変数に保存したセッションデータは、エクステンションがファイルやデータベースなどのストレージに保存します。2回目以降のHTTPアクセスでは、ストレージに保存してあるデータを読み出して$_SESSIONに格納します。このような仕組みで、あたかも$_SESSIONという変数を別々のHTTPアクセスの間で共有しているように振る舞うわけです。
セッションデータはどこに保存する?
Webアプリケーションでセッションを使うときは、最初にセッションデータを保存する場所について考えなければなりません。標準設定では1つ1つのセッションごとに、ファイルを1つずつファイルシステムに保存するようになっています。セッションデータを保存する場所と方法は、開発者がプログラムを開発することでいろいろ変えることができます。例えば、MySQLなどのデータベースや、memcachedなどのメモリキャッシュシステムなどにも保存できます。
セッションの保存先を決めるときは、以下に挙げる要因を考えるとよいでしょう。まずは同時利用者数、つまり同時に処理するセッション数です。そして、時間当たりのアクセス数。さらに、セッションに保存するデータの大きさです。ほかにもセッションの保存先の決定に影響する要因はありますが、まずはこの3つの要素を考えるとよいでしょう。
また、複数のWebサーバによる並列処理で負荷分散をする場合は、保存したセッションデータはそれぞれのWebサーバで共有できなければなりません。ファイルに保存してしまっては共有できません。専用のデータベースサーバを用意して保存するなどの手段を考える必要があります。
今回は並列処理が必要になるほど負荷がかかる状況は想定せず、シンプルにファイルに保存することにして、セッションを利用する方法を解説します。ファイルに保存する場合、標準の状態では保存ディレクトリは/tmpとなっています。
第40回でユーザーがWebブラウザからアップロードしたファイルの保存先が標準で/tmpになっていることの問題点を解説しました。セッションデータを保存するディレクトリも/tmpです。同じような問題が発生することは十分考えられます。
第40回では、大きく分けて2つのポイントを解説しました。/tmpがtmpfsという一時ファイル用のRAMディスクになっていることがあり、ここに大きなファイルを置くとメモリ領域を圧迫してしまうこと。もう1つは、/tmpが/(ルート)を含むパーティションの一部となっていると、/varなどのOSに必要なストレージ領域を圧迫する可能性があるということです。
セッションの保存先を決めるときも、やはり第40回で解説したようなポイントに注意する必要があります。ただし、ユーザーがアップロードしたファイルと、セッションデータを比較すると、アクセス頻度やデータサイズがまるで違います。まず、セッションデータはHTTPのアクセスがあるたびに読み書きが発生します。ディスクよりメモリに保存した方が、性能を上げられる可能性が上がるということになります。
そして、セッションのデータはアップロードファイルに比べればデータサイズは小さくなります。つまり、セッションデータをtmpfsの領域に保存するようにしても、メモリ領域を大量に消費することはありません。メモリに余裕があるのなら、tmpfsの領域に保存するようにしておくのがよいでしょう。
では、/tmpがtmpfsであればデフォルトの/tmpのままでよいかというと、そうでもありません。セッションはバーチャルホストごとにできるデータですので、バーチャルホスト内で共有できるように、それぞれのバーチャルホストのディレクトリに保存すべきです。それに/tmpはOSが一時ファイルに使います。やはりセッションデータが領域を圧迫するという問題が発生することも考えられます。
以上で説明した事情を考えて、この連載では各バーチャルホストにセッション保存ディレクトリをtmpfsで作成することにします。
セッション用のtmpfs領域を作る
本連載では、「/srv/httpd/バーチャルホスト名/」という構成でバーチャルホストごとにディレクトリを用意しました。さらに、この中にログを保存するディレクトリ「logs」や、Web公開ディレクトリ「webspace」があります。また、前回はPHPが読み書きするファイルを置くために「phpdata」というディレクトリを作成しました。これらのディレクトリと同じようにセッションデータを置く「phpsession」を作ることにします。まずは以下のようにコマンドを実行してディレクトリを用意します。
$ sudo mkdir /srv/httpd/www3026ub.sakura.ne.jp/phpsession
続いて、このディレクトリにtmpfsの領域をマウントします。マウントするだけならmountコマンドで済むのですが、OSを再起動しても起動するたびに自動的にtmpfsの領域をマウントするように、/etc/fstabという設定ファイルに次の行を加えます。
tmpfs /srv/httpd/www3026ub.sakura.ne.jp/phpsession tmpfs size=32m,mode=700,uid=daemon,gid=daemon 0 0
行の中ほどに「size=32m」という記述があります。これがtmpfsのサイズになります。ここでは32Mbytesに設定しました。「mode=700」はマウント後のパーミッションを表しています。「700」は所有者のみの読み書きとなります。「uid=daemon,gid=daemon」はディレクトリの所有ユーザーとグループを示しています。セッションはPHPが読み書きしますので、所有者はApacheの実行ユーザーと一致させなければなりません。
/etc/fstabに行を追加したら、マウントするために次のコマンドを実行するか、OSを再起動してください。
$ sudo mount /srv/httpd/www3026ub.sakura.ne.jp/phpsession
これでphpsessionディレクトリをtmpfsでマウントできました。ストレージの状況を確認しましょう。
$ df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/hda2 ext3 17G 3.1G 13G 20% /
/dev/hda1 ext3 99M 36M 58M 39% /boot
tmpfs tmpfs 753M 0 753M 0% /dev/shm
/dev/hdb1 ext3 30G 4.3G 24G 16% /home
tmpfs tmpfs 32M 0 32M 0% /srv/httpd/www3026ub.sakura.ne.jp/phpsession
さらに、バーチャルホストのディレクトリ内にあるそれぞれのディレクトリのパーミッションも確認しましょう。
$ ls -l /srv/httpd/www3026ub.sakura.ne.jp
total 20
-rw-r--r-- 1 root root 587 Feb 9 18:29 apache.conf
drwxr-xr-x 2 root root 4096 Feb 2 05:23 logs
drwxr-xr-x 2 daemon daemon 4096 Feb 9 18:29 phpdata
drwx------ 2 daemon daemon 40 Feb 16 04:05 phpsession
drwxr-xr-x 3 root root 4096 Feb 9 18:29 webspace
期待通り、32Mbytesの領域としてマウントされ、またdaemonからのみ読み書きできるディレクトリとなっています。これで保存ディレクトリができました。次にバーチャルホストごとのApache設定ファイルである「/srv/httpd/www3026ub.sakura.ne.jp/apache.conf」に次の行を追加します。
PHP_Value session.save_path /srv/httpd/www3026ub.sakura.ne.jp/phpsession
「session.save_path」はセッションデータを保存する場所を設定するディレクティブです。このディレクティブは、sessionエクステンション固有のディレクティブです。ディレクティブの名前の先頭に「session」とエクステンション名が付いていることがその事実を示しています。
セッションの動作を試す
セッションが働いているのか試してみましょう。まず、session_set.phpという名前で次のプログラムをWeb公開ディレクトリに設置します。セッションにGETメソッドで得たリクエストデータを保存するものです。
<?php
session_start();
$_SESSION['test'] = $_GET['test'];
?>
もう1つ、セッションの内容を表示するプログラムであるsession_get.phpをWeb公開ディレクトリに設置します。
<?php
session_start();
echo $_SESSION['test'];
?>
curlコマンドで確認してみましょう。ただし、セッションはクッキーを使うので、クッキーの保存と送信を示すオプションを忘れないでください。「-c ファイル名」が保存で、「-b ファイル名」が送信です。
$ curl -c cookie.dat -b cookie.dat 'http://www3026ub.sakura.ne.jp/session_set.php?test=foobar'
$ curl -c cookie.dat -b cookie.dat http://www3026ub.sakura.ne.jp/session_get.php
foobar
1回目のリクエストで送信したデータ(「?test=foobar」)が、セッションを経由して2回目のリクエストで表示されました。セッションはちゃんと動作しています。セッション保存ディレクトリを見てみましょう。
$ sudo ls /srv/httpd/www3026ub.sakura.ne.jp/phpsession
sess_7a0fbe05e6315cd9a617c84f4c8f043b
ファイルが作成されていることが確認できます。ついでにそのファイルの中身を見たところ、次のようになっていました。
$ sudo cat /srv/httpd/www3026ub.sakura.ne.jp/phpsession/sess_7a0fbe05e6315cd9a617c84f4c8f043b
test|s:6:"foobar";
セッション変数である$_SESSIONに格納した値が保存されている事が見て取れます。セッションについての解説は以上です。本稿の残りの部分では、今まで説明しきれなかったPHPの実行時設定をいくつか取り上げ、設定法を解説します。「今まで説明しきれなかった」と表現すると、あまり重要な設定項目ではないと思ってしまう人もいるかもしれませんが、以下で説明する設定項目はすべてきちんと設定しておくべきものです。
タイムゾーンの指定
本連載では、設定を確認するために、phpinfo()を何度も実行してきましたが、その途中でエラーメッセージが出ていたことに気付いた方もいるかもしれません。これはタイムゾーンを設定していないため、日付データを操作するdateエクステンションが出力している警告メッセージです。ログには次のようなメッセージが残ります。
[Thu Feb 16 06:11:08 2012] [error] [client 210.255.86.78] PHP Warning: phpinfo() [<a href='function.phpinfo'>function.phpinfo</a>]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Asia/Tokyo' for 'JST/9.0/no DST' instead in /srv/httpd/www3026ub.sakura.ne.jp/webspace/phpinfo.php on line 2
php.iniに次の行を加えれば、エラーメッセージの出力はなくなります。エラーメッセージ中にあるとおり「date.timezone」ディレクティブでタイムゾーンを指定するのです。
date.timezone = Asia/Tokyo
特定のファンクションを無効にする
脆弱な部分を作ることにつながる可能性が高い、リスクのあるPHPのファンクションはそもそも使わないとする開発方針もあります。それを強制するのが「disable_functions」ディレクティブです。使用不可能にするファンクションの名前をカンマ区切りで指定します。ただし、この設定はphp.iniにしか記述できないことに注意してください。バーチャルホストごとに設定を上書きすることもできません。
disable_functionsディレクティブで無効にしておきたいファンクションとしては、外部プログラムの実行に関係するものが挙げられます。これは前回、開けるファイルを限定したのとまったく同じ理由による判断です。バグやミスによって、リクエストデータで実行ファイル名が制御できてしまうと、任意のコマンドが実行できてしまうためです。
disable_functionsディレクティブは、以下のように設定しておくと良いでしょう。
disable_functions = exec,shell_exec,system,popen,proc_open,passthru,show_source,parse_ini_file,dl
まとめ
今回の解説内容を考えてphp.iniの内容をまとめると、次のようになります。
memory_limit = 32M
max_execution_time = 30
expose_php = Off
magic_quotes_gpc = Off
variables_order = GPCS
register_long_arrays = Off
register_argc_argv = Off
post_max_size = 64K
max_input_vars = 100
upload_tmp_dir = /home/uploads
upload_max_filesize = 1
display_errors = Off
display_startup_errors = Off
log_errors = On
error_reporting = E_ALL | E_STRICT
open_basedir = /srv/httpd
allow_url_fopen = Off
date.timezone = Asia/Tokyo
disable_functions = exec,shell_exec,system,popen,proc_open,passthru,show_source,parse_ini_file,dl
次回からはMySQLの解説に入ります。
仕事で使える魔法のLAMP バックナンバー 連載インデックスへ»
- 第1回 LAMP環境、自分で作りませんか?
- 第2回 サーバに接続して、一般ユーザーのアカウントを作る
- 第3回 アクセス制限の設定とCentOSのアップデート
- 第4回 sshを便利にする公開鍵暗号
- 第5回 公開鍵認証でsshを安全に使う
- 第6回 「ビルド」という作業は何を指しているのか
- 第7回 ダイナミックリンクとスタティックリンク
- 第8回 makeを使ってソフトウェアをビルドしてみよう
- 第9回 Makefileをいろいろ書き換えながらビルドしてみよう
- 第10回 ダウンロードファイルが真正なものであるかを確認
- 第11回 配布パッケージの中身と、configureの役目を知る
- 第12回 configureの設定を変更してみる
- 第13回 configureでソフトウェア固有の設定を変更してみる
- 第14回 Apache HTTP Serverのビルドを始めよう
- 第15回 ライブラリが足りなくてビルドできないときは?
- 第16回 proxyやsslのモジュールを使ってみる
- 第17回 OpenSSLをビルドしてApacheで利用する
- 第18回 Apache同梱ソフトウェアに引数を渡してビルド
- 第19回 認証DBにアクセスするライブラリを組み込む
- 第20回 サードパーティのApacheモジュールをビルドする
- 第21回 Apacheの設定ファイルを記述する前に
- 第22回 1つのサーバに複数の仮想サーバ?
- 第23回 設定ファイルや公開ドキュメントの配置を考える
- 第24回 設定ファイルを作成してApacheを動作させる
- 第25回 PHP編に突入! まずはソースをダウンロード
- 第26回 早速PHPをビルド! そしてテスト!
- 第27回 PHPテスト失敗の原因を追究する
- 第28回 エクステンションを有効にしてビルドに挑戦!
- 第29回 XMLを処理できるようにする
- 第30回 PHPでデータベースを使う準備をする
- 第31回 エクステンションの組み込み状況を確認する
- 第32回 単純なデータを管理するDBMを使えるようにする
- 第33回 PHPエクステンション組み込みの仕上げ
- 第34回 PHPスクリプトを実行できるようにする準備
- 第35回 PHPの設定ファイルを作って配置してみる
- 第36回 Apacheの設定ファイルでPHPの設定を変える
- 第37回 安全を考えてPHPの実行時設定を調整する
- 第38回 マジッククオート機能には頼らない
- 第39回 リクエストデータを受け取る変数の扱い
- 第40回 ファイルのアップロードを制限する
- 第41回 エラーメッセージをどう扱うか?
- 第42回 クライアントがアクセスできる範囲を制限する
- 第43回 PHPでセッションを利用するための設定
- 第44回 いよいよMySQL編、ソースからビルドすべきか?
- 第45回 MySQLのビルドに欠かせないCMakeを準備する
- 第46回 CMakeでMySQLをビルドしてみる
TechTargetジャパン
- OSSライセンスの採用傾向に「変化」あり (2012/5/21)
OSS普及の一翼を担ってきたライセンス、GPLファミリー採用の割合が減少傾向にあるそうです。いったいどうして? - ここからFirefoxの反撃が始まる (2012/3/12)
2月のLinux SquareのランキングではFirefoxの記事がダントツのページビューを集め、トップに立ちました - CMakeでMySQLをビルドしてみる (2012/3/8)
ここまでの作業でCMakeを使う準備が整いました。今回はひとまずMySQLをビルドしてみます - MySQLのビルドに欠かせないCMakeを準備する (2012/3/2)
今回は、MySQLをビルドするために欠かせないツール「CMake」をインストールし、使う準備をします
|
|
キャリアアップ
スポンサーからのお知らせ
- - PR -
イベントカレンダー
- - PR -

