TRY AND ERROR

気になったこと、勉強したこと、その他雑記など色々メモしていきます。。Sometimes these posts will be written in English.,

【PHP】sessionとcookieについて

今回はsessionとcookieについて少しおさらい。
あとPHPで具体的にどう使うか、についても触れておきます。

sessionとcookieって?

大まかに言うと、両者ともある一定期間データを保存しておく仕組みです。
ただ、データをサーバ側に保存しておくのか、クライアント(ブラウザ)側に
保存しておくのかという点が異なり、サーバ側に保存するのがsession、クライアント側に保存するのがcookieです。。

こんなところで使われている

ネットショップなどで買い物する際に、一度ログインすると一定期間ログイン状態が保持されることがあると思います。この仕組みにsessionとcookieが使われています。
(ざっくりと言うと)sessionにユーザー情報を保存しておき、cookieにsessionを特定するためのID(仮にsessionIDとしておきます)を保存しておきます。サイトにアクセスされた際に、cookieに保存されたsessionIDをキーにsession情報を呼び出し、ログイン状態を再現するというわけです。
なので、sessionが使われる場合はcookieも使われることになります。

PHPでsessionとcookieを使ってみる

実際にPHPでは以下のように記載します。

cookie

setcookie('クッキー名','値','有効期限','クッキーが有効なパス')でcookieを作成することができます。

setcookie('testCookie', 'クッキー', time()+3600, '/');

実際にcookie情報を見てみると、上記で作成したものが表示されています。
f:id:tamago-engineer:20150602233604p:plain

firefoxの場合、cookie情報はfirebugというプラグインを入れるとみることができます。



session

session_start()でセッションを開始し、$_SESSION変数に値をセットしていきます。
以下の例では'test'という名前のsession変数に'テスト'という値をセットしています。

session_start();
$_SESSION['test'] = 'テスト';


該当ページでsessionが使われると、クライアント側(ブラウザ)にsessionを特定するためのIDを格納したcookieが作成されます。
ブラウザのcookie情報を見てみると、クライアント側には'PHPSESSID'という名前のcookieにsessionIDが保存されていました。
f:id:tamago-engineer:20150602225412p:plain



サーバ側でsession_id()を実行するとsessionIDを取得することができます。
試しに出力してみると、cookieに保存されていたsessionIDと同じものが確認できました。

echo session_id();

ーーーーー結果ーーーーー
9mcbahq5vof3ccht496h3r16h7


sessionIDが保存されるcookieに有効期限を指定することもできます。
以下の例では、有効期限を60秒間としています。

session_set_cookie_params(60);
session_start();
・・・

cookie情報からも有効期限が設定されていることがわかります。
f:id:tamago-engineer:20150602231236p:plain


cookieとして保存されたsesssionIDは改竄される可能性もあります。
この対処法としてsession_regenerate_id()というメソッドを使うと、
sesssionIDを新しいものにしてくれます。
session_regenerate_id(true)とすると、古いsession情報を削除することができるので、無駄なリソースを削減するために行っておいたほうが良いと思います。

session_regenerate_id(true)を連発するとsessionが切れるバグがあります。例えば、連続でリロードされた場合やsubmitボタンを連打された場合などに切れてしまうことがあるとか。。。新しいIDを生成してそこにセッション情報をコピーするといったような処理を行っているため、短時間に連続リクエストされると不都合が出てしまうのか・・・?
なんにせよ、不用意にsession_regenerate_id(true)を連発するのは危険なので、
jsで連続リクエストを防止するとか、PHPで一定確率でsession_regenerate_id(true)を行うようにするとか、対策が必要です。


セッション情報をすべて削除したい場合、session_destroy()というメソッドを使います。ただ、session_destroy()はcookieの削除までは行ってくれないため、
自前で削除する必要があります。

setcookie('PHPSESSID', '', time() - 1800, '/');
session_destroy();

setcookieはcookieをセットするメソッドですが、第3引数の有効期限を過去にすることでcookieを削除することができます。

ちなみに、特定のsession変数のみ削除したい場合はunset($_SESSION['XXX'])を使います。