Buno Journals

It's what I do that defines me.

PHPでセッション管理のメモ

以下、PHPのセッション管理についての簡単なメモだ。

セッション管理とクッキー

セッション管理

HTTP自体はステートレスなプロトコルでサーバ側で状態を保持しない。 しかし、ログイン後の認証状態、ECサイトのショッピングカートなど、アプリケーションによっては状態を保持しておく必要がある。 このように、ユーザ毎にサーバ側での状態を覚えておくことセッション管理という。

クッキー

セッション管理をHTTPで実現するための仕組みがクッキー(cookie)だ。

サーバ側からの指示に従い、ブラウザは「名前=変数」の組を記憶する

セッション開始

以下、動作確認しながら説明する。

次のファイルは、session_start() 関数でセッションを開始するサンプルである。

sessiontest1.php

<?php
    session_start();
?>

<html>
<head><title>PHP TEST</title></head>
<body>

<?php

    if (!isset($_COOKIE["PHPSESSID"])){
        print('初回の訪問です。セッションを開始します。');
    }else{
        print('セッションは開始しています。<br>');
        print('セッションIDは '.$_COOKIE["PHPSESSID"].' です。');
    }

?>

</body>
</html>

初めてこのファイルにHTTP GETでアクセスした場合、 レスポンスにはSet-Cookieヘッダがあり、 この情報をブラウザに記憶するように指示している。

f:id:bunoacts:20160709155543p:plain

ちなみにChromeの場合はフォームに chrome://settings/cookies と入力すれば

記憶しているCookieを確認することができる。

f:id:bunoacts:20160709155743p:plain

そして、再度このページにHTTP GETでアクセスする時は、 リクエストのCookieヘッダに記憶した情報が付与されている。

f:id:bunoacts:20160709160158p:plain

ここでやり取りされていたPHPSESSID=****という情報はセッションIDといい、 サーバに保存されている全てのユーザのセッション情報の中で、ユーザを特定するためのIDである。

なお、セキュリティの観点から、認証(ログイン)後、セッションIDを更新した方がよい

ちなみに、PHPSESSIDはセッション名といい、phpの場合はphp.iniファイルでデフォルト値として設定されており、 変更することも可能だ。 そして、この値は session_name() 関数で取得できる。 つまり、クッキーに保存されたセッションIDは$_COOKIE[session_name()]と書いても取得できる。

セッションの管理と終了

サーバ側で管理したいセッション情報は、$_SESSION連想配列を使って管理する。 このセッション情報はWebサーバ上のファイル保存される。

そして、ログアウト時には、以下のような処理が必要になる。

  • サーバ側で保存しているセッション情報を削除
  • クライアント(ブラウザ)側のCookie情報の削除

よって、phpでは以下のような処理を行う。

<?php

// 空の配列を代入して、全てのセッション変数をクリアする。
$_SESSION = array();

// ブラウザのクッキーを削除。実際には、クッキーの有効期限に過去の時間をセットしている。
setcookie("PHPSESSID", '', time() - 1800, '/');

// セッションファイルを削除する
session_destroy();

?>

session_destroy();でセッションファイルを破棄すれば、 $_SESSION = array();のようなセッション変数を初期化する処理は不要ではないのか、と思ってしまったが、 私が動作確認したところ、同一スクリプト内ではsession_destroy();実行後であっても$_SESSIONのセッション変数はクリアされておらず、 アクセス可能だった。 やはり、セッション変数の初期化とセッションファイルの削除を両方やっておくべきのようだ。

クッキーの属性

コッキーを発行する際、様々なオプション属性を設定することができる。

属性 意味
Domain ブラウザがクッキー値を送信するサーバのドメイン
Path ブラウザがクッキー値を送信するURLのディレクト
Expires クッキー値の有効期限。指定しない場合はブラウザ閉じるまで
Secure SSLの場合のみクッキーを送信
HttpOnly JavaScriptからこのクッキーにはアクセス不可

Domain属性

デフォルトでは、クッキーはセットされた元のサーバのみに送信する。セキュリティ的には、これが安全なので原則としてDomain属性は設定しない

Domain属性を指定するのは、複数のサーバに送信されるクッキーを生成したい場合だ。 例えば、Domain=example.jpとして生成したクッキーは a.example.jp にも b.example.jp にも送信される。

仮に、a.example.jpサーバがSet-CookieヘッダでDomain=example.comとしても、このクッキーはブラウザに無視される。 セッションIDの固定化攻撃の手段にならないように、異なるドメインに対するクッキーは設定できないようになっている。

HttpOnly属性

クッキーに格納されたセッションIDを盗み出す手段として、クロスサイトスクリプティングによりJavaScriptを悪用してクッキーを盗み出すというものがある。 この属性を設定することで攻撃を難しくすることはできる。 phpの場合は、php.iniファイルで以下のように設定を追加する。

session.cookie_httponly = On

参考

体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践

体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践

PHP: $_SESSION - Manual

$_SESSION = array() と session_destroy(); の関係性。 - PHP 解決済 | 教えて!goo

セッション管理 - PHP入門

ChromeのCookieデータの場所と覗く方法

10日で覚えるPHPのキソ 第 10 回 セッション(SESSION) | バシャログ。