WEBページへのアクセスは問い合わせから情報出力までの流れで処理が完結してしまうため、前のページにアクセスした際に造られたデータは、そのままでは次のページで利用ができません。

そこでWEBではセッションという一連の処理の流れを纏めて管理するための仕組みが利用されます。

この章ではセッションの利用の仕方を学びます。

※この記事は執筆・公開から3年以上経過しています。記事の情報が古くなっている場合がありますのでご注意ください。

公開日時:2016/02/16 19:48
最終更新:2019/12/10 01:54

セッションの利用~ 365日の紙PHP(9日目)

さて、昨日はログインフォームからの送信先を自分自身にすることで、フィールドに入力された内容が消えないような改造を施しました。

通常、ログインした先には複数のページが存在します。ログインしないでそれらのページにアクセスできては困りますから、ユーザーがログインしているかどうかを各ページで判定する必要がでてきます。

どのようにしてログイン済みのユーザーであるかを判定したら良いでしょうか?

ユーザーのブラウザにIDとパスワード情報を持たせておいて、ログインフォームの時のようにアクセスする度にそれを送信するのはどうでしょう? それはあまり良い方法ではないでしょう。IDとパスワードは重要な情報なのでそう頻繁に送信すべきではありません。

では、ログインしたらチケットを発行してユーザーのブラウザに持たせ、アクセするたびにそのチケットを送信しさせたらどうでしょう?

これはなかなか良さそうですね。サーバー側は、送信されたチケットが正しいものか調べる事でログイン済みかどうかを判断できます。正しくなければログイン画面にリダイレクトさせます。

今日はこの機能を実装してみましょう。

セッションを使ってみよう

このようなログイン管理をする時、PHPでは通常、セッションという機能を使います。

まず index.php の先頭で、セッション機能を使う宣言をしましょう。

<?php

    session_start();

    $allow = array(
        "taro" => '$2y$10$9xUPdF/l2deV2gCo2BbqAeJ6Znh1eTDfQ4e7Rgy0Jy8lzvmyYIZcu',
        "hanako" => '$2y$10$nBaOXLHZgXAGobWD1JZMxOnLUwQ1BAYdxJpyqQSJRfVxRwQ/o6ln2',
        "kenji" => '$2y$10$u2GdyeCYUtImZAgkyqlpYeWrIsuLwmXtsxCzCOX7NHhEO/q0AkBE.',
    );

このように session_start(); を宣言することで、セッション機能が有効になります。注意点としては session_start() する前に文字列等を出力してはいけません。このため、通常はPHPコードの最初の方で session_start() する事になります。

次は、IDとパスワードの照合が成功したら、login.php にリダイレクトする前にセッション変数を定義します。

    if($login_ok === true){

        $_SESSION["logged"] = true;
        $_SESSION["user_id"] = $_POST["user_id"];

        http_response_code(200);
        header("Location: login.php");
        exit;
    }

$_SESSION["logged"] が配列であるということはもうお分かりいただけると思います。$_SESSIONに、logged というキーで true (真) を、user_id というキーで入力された user_id を設定しています。$_SESSIONには自由にキーと値の組み合わせを設定できます。

最後に、ログイン後の画面である login.php の先頭に次のようなPHPコードを書きます。HTML内の$_POST["user_id"] は $_SESSION["user_id"] にします。

<?php

    session_start();

    if(!isset($_SESSION["logged"])){
        http_response_code(403);
        header("Location: index.php");
        exit;
    }

?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <h1>ようこそ</h1>
        <p>ログイン処理が成功しました。ようこそ<?php echo $_SESSION["user_id"] ?>さん。</p>
    </body>
</html>

先頭では再び session_start() を記述し、このページでもセッションを使うことを宣言しています。

あとは、$_SESSION["logged"] が定義されていなければ index.php にリダイレクトする処理ですが、if文の !isset() は () 内の値が定義されていなければ、という意味です。 isset() は () 内の値が定義されていればという意味で、! はその反対、つまり、定義されていなければとなっています。

ここまでコードを書いたら実際にログインしてみましょう。正しいIDとパスワードの組み合わせでログイン出来ることを確認して下さい。

ログイン確認

確認したら、一旦ブラウザをすべて閉じ、再びブラウザを起動して今度はアドレスバーに直接

http://localhost/login.php

を入力してみましょう。index.php にリダイレクトされたはずです。

未ログインでのリジェクト処理の確認

どういう仕組みになっているか調べてみましょう。Firefox か Chrome でログインの処理をした後、以下のような操作をして下さい。

Firefoxの場合

右上のバーアイコンから開発ツールボタンをクリックし、開発ツールバーを選んで下さい。

firefoxでのセッション情報の確認

画面下に開発ツールバーが表示されるので、そこに cookie list とタイプしてエンターを押して下さい。

cookie listのアクセス方法

以下の様なリストが表示され、その中にPHPSESSIDという値があるはずです。

セッションIDの確認

Chromeの場合

右上のバーアイコンからその他のツールボタンをクリックし、デベロッパー ツールを選んで下さい。

chromeでのセッションIDの確認方法

デベロッパーツールが表示されるので Resources から Cookies の localhost で PHPSESSID を確認して下さい。

chromeでのセッションID確認

PHPSESSID とは

PHPSESSID というのは、PHPでのデフォルトのセッションIDキーです。これは PHP の設定ファイルである php.ini に定義されています。

XAMPP の方はコントロールパネルの Apache の Config から PHP (php.ini) で内容を確認して下さい。MAMP の方は /Applications/MAMP/bin/php/php5.6.10/conf/php.ini にあるはずです(PHPのバージョンが違う場合は読み替えて下さい)。

php.ini で [Session] を検索してみましょう。次のようなコードが確認できると思います。(抜粋)

[Session]
; Handler used to store/retrieve data.
; http://php.net/session.save-handler
session.save_handler=files

(略)

session.save_path="D:\xampp56\tmp"

; Whether to use cookies.
; http://php.net/session.use-cookies
session.use_cookies=1

(略)

; Name of the session (used as cookie name).
; http://php.net/session.name
session.name=PHPSESSID

(略)

上記の session.name が、デフォルトのセッションID用のキーです。session.use_cookiesが1(true)になっているので、セッションIDは cookie でユーザーに渡されます。また、session.save_handler が files になっていますのでセッションはファイルとして保存され、その場所は session.save_path の場所です。こちらの環境では XAMPP を xampp56 という名前でDドライブにインストールしたので上記のようになっています。

さて、では session.save_path に指定されている場所のフォルダを開いて、セッションがどのようなファイルで保存されているか見てみましょう。

保存されたセッションファイルの確認

保存先にはこのように複数のファイルがありますが、sess_ で始まるファイルが PHP のセッション保存ファイルです。sess_ の後に先ほど確認した PHPSESSID の値が続くファイルをテキストエディタ開いてみましょう。

セッションファイルの中身

logged|b:1;user_id|s:4:"taro";

このような値が保存されています。logged と user_id はキーですね。|でキーと値を分離しています。そのペアを ;(セミコロン)で区切っています。

b は boolean(真偽値)の略です。先ほど $_SESSION["logged"] に true を設定しました。このようにプログラムでは false と 0、true と 1 を同等に扱うことがよくあります。

s は string(文字列)の略です。その後の数字は文字列の文字数のようですが、正確には文字列のデータ量でバイト数です。日本語の文字は1文字で数バイトが必要であったりしますので見かけ上の文字数とここの数字は一致しません。

どうでしょう? ブラウザに cookie というもので記号の羅列が渡されていて、$_SESSION に設定した値がその記号の羅列のファイル名で書きだされていることはお分かりいただけたでしょうか?

この記号の羅列が最初にお話したチケットの役割をしています。

以後、これが繰り返されます。

初めてアクセスしてきたユーザーはセッション変数が設定されていないのでログイン画面に強制的にリダイレクトされますが、1度ログインしたユーザーは cookie にセッションIDが記録されていてそれが送信されるため、サーバーのセッション保存ファイルが削除されない限りログイン後の画面にアクセスできるわけです。

セッションの保存時間

セッションファイルの保存時間はデフォルトで1440秒(session.gc_maxlifetime)で、つまり24分ですが、この時間を超えたら必ずセッションファイルが削除されるわけではありません。まず、ユーザーが誰もアクセスしてこなければセッションファイルは永久に残っています。

そして、誰かがアクセスしてくる度に、有効期限が切れたSESSIONのみが、 php.ini で設定されている session.gc_probability / session.gc_divisor の確率で削除されます。例えば XAMPP では session.gc_probability = 1、session.gc_divisor = 1000 のようなので、session.gc_maxlifetimeを超えたセッションファイルは 1/1000 の確率で削除されます。

これをわかりやすく説明すると、例えばある人がログインしたまま24分間一切次のアクセスをしなかったとしても、セッションは切れません。24分を超えた段階で別のユーザーがアクセスするたびに1/100の確率でセッションが破棄されます。ですから、30分後に再びリクエストを送信した時にはセッションが切れているかもしれませんし、まだ繋がっているかもしれません。

セッションの使い方は大体おわかりいただけたでしょうか?

纏めると、セッションを使うには、

  1. session_start() する。その前に出力は行わない。
  2. セッションには$_SESSIONで値を保存できる。
  3. セッションIDはデフォルトで cookie に保存される。
  4. サーバーのセッション保存最短時間はデフォルトで最短24分。

さしあたって、この4つが理解できればセッションは使えます。それほど難しくはありませんね。

ただし...

もう一つ、知っていなければならないとても重要な事があります。それを知らないと、あなたが作るシステムにはとても大きな穴が開いているのと同じ状態になってしまいます。

セッションは便利なのでほとんどのシステムで利用することになると思いますから、絶対にこれは理解していなければなりません。

その重要な事については、明日ご説明します。

もし余裕がある方は、今日のところは php.ini の設定を眺めてみたり、セッション変数をいろいろといじって試してみてください。

お疲れ様でした。

記事リンク