PHP - WEB - 11. セッションの詳細

引き続きセッションについて学習していきましょう。Webアプリケーションにおいてユーザとの一連のやりとりの間で発生するデータを保存するにはセッションという仕組みを使います。PHPにおいて、セッションを利用するためには予め session_start 関数を呼び出した後、 $_SESSION 変数にアクセスします。それでは、このときWebブラウザとWebサーバ間のHTTP通信ではどのようなデータのやりとりが行われているのでしょうか。ここでは具体的なHTTP通信のやりとりを中心に見ていくことにします。

Cookie

一般的にセッションはその内部でCookieという仕組みを使います。CookieとはHTTPのクライアント(Webブラウザ)上に少量のデータを保存する仕組みです。もともとHTTPの通信ではWebサーバからWebブラウザ上のコンピュータに対してファイルを作成したり、削除したりといった操作は禁止されています。これを許可してしまうとWebサーバから、Webブラウザを使っている利用者のコンピュータを自由に操作できてしまうためです。そのような背景においてCookieはWebサーバからWebブラウザ上にデータを残すことのできる例外的な仕組みです。

CookieはPHPの連想配列のようにキーと値の組み合わせでデータを管理します。ただし、 Cookieには様々な制約があります。たとえば1つのキーに指定可能な値には、少量のデータ(数KB程度)しか保存できないようになっています。

Cookieへのデータの保存

WebサーバからWebブラウザ上のCookieにデータを保存するためにはHTTPレスポンスに Set-Cookie ヘッダを付与します。具体的には次のようなヘッダフィールドです。

Set-Cookie: Key1=Value1; path=/

レスポンスの中に上記のような Set-Cookie ヘッダが存在する場合、Webブラウザは Cookieに Key1 というキーと Value1 という値のペアを保存します。

Cookie上のデータの送信

Cookieに保存されたデータは、Cookieを作成した同一ドメインへのリクエスト時に、自動的にリクエストのヘッダフィールド( Cookie ヘッダ)に含まれるようになります。

Cookie: Key1=Value1

あるドメインによってCookieに保存されたデータは、別のドメインへのリクエストに含まれることはありません。

PHPプログラムの開発(セッションの仕組み)

ここではさきほどのログイン処理でのやりとりをもとに、実際にどのようなデータ通信が発生して、 Cookieへのアクセスが発生するのかを確認してみましょう。またここではChromeを起動する際にシークレットモードで起動することにします。これはわかりやすくWebブラウザ上のCookieを空の状態にして動作確認するためです。

Chromeをシークレットモードで起動するには ctrl + shif + n キーをタイプします。

ビルトインWebサーバを起動した状態で、Webブラウザからログイン画面( login.html )にアクセスします。

http://localhost:8000/login.html

ログイン画面が表示されるのでデベロッパーツール(Networkタブ)を開いた状態でIDに Andy 、パスワードに secret と入力してログインボタンをクリックしましょう。そうするとログイン処理( login.php )へのHTTP通信と、リダイレクト後のメニュー画面表示処理( menu.php )へのHTTP通信2つのキャプチャーが取得できます。

ここではまずログイン処理( login.php )のレスポンスを確認してみましょう。

次のようなHTTPレスポンスを確認できるでしょう。

HTTP/1.1 302 Found
Host: localhost:8000
Date: Mon, 17 Aug 2020 13:20:29 GMT
Connection: close
X-Powered-By: PHP/7.3.11
Set-Cookie: PHPSESSID=1j49ibl7m223hh6k28pmf4s1un; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Location: menu.php
Content-type: text/html; charset=UTF-8

このレスポンスはメニュー画面表示処理へのリダイレクトを指示しているので、ステータスコードは 302 、また Location ヘッダには遷移先である menu.php が指定されています。このとき Cookie にデータを保存する Set-Cookie ヘッダが付与されている点に注意してください。

Set-Cookie: PHPSESSID=1j49ibl7m223hh6k28pmf4s1un; path=/

この Set-Cookie ヘッダによって、 Cookieに PHPSESSID キーで 1j49ibl7m223hh6k28pmf4s1un という値が保存されます。この PHPSESSID という名前のキーはセッションIDと呼ばれるものです。この場合、ユーザのセッションID( PHPSESSID )は 1j49ibl7m223hh6k28pmf4s1un となり、Webサーバ上でユーザのセッションを識別する用途に利用します。

セッションを実現するために必要なネットワーク上のやりとりはセッションIDに限定されます。 $_SESSION 変数に保存した "id""time" キー、またそれぞれのキーに紐づく値は、セッションIDと関連付けられてサーバサイドに保存されます。

さいごにHTTPレスポンスになぜ、このような Set-Cookie ヘッダが付与されたのかという疑問が残ります。これはログイン処理( login.php )において session_start 関数を呼び出しているためです。PHPでは session_start 関数を呼び出すことで、セッションの管理に必要なHTTPレスポンス(この場合 Set-Cookie ヘッダ)を生成するようになっています。

Set-Cookie ヘッダの挙動を上手く動作確認できない場合は、Chromeを一度閉じて、改めてシークレットモードで動作を確認してください。

以上の結果としてログイン処理( login.php )のレスポンスを受け取ったWebブラウザはCookieに PHPSESSID キーと 1j49ibl7m223hh6k28pmf4s1un のような値を保持することになります。

続いてChromeのデベロッパーツール(Networkタブ)から、リダイレクト時のメニュー画面表示処理( menu.php )へのリクエストも確認しておきましょう。

次のような通信データを確認できるでしょう。

GET /menu.php HTTP/1.1
Host: localhost:8000
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6)...省略
Accept: text/html,application/xhtml+xml,application/xml;q=0.9...省略
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8000/login.html
Accept-Encoding: gzip, deflate, br
Accept-Language: ja,en-US;q=0.9,en;q=0.8
Cookie: PHPSESSID=1j49ibl7m223hh6k28pmf4s1un

このリクエストはさきほどの Set-Cookie ヘッダを受信した際のドメインと同一ドメインへのリクエストに該当するので、リクエストには Cookie ヘッダが付与されているのがわかります。

Cookie: PHPSESSID=1j49ibl7m223hh6k28pmf4s1un

WebブラウザからWebサーバに送信される Cookie ヘッダはPHPから参照可能となります。またサーバ上にはユーザ(セッションID)に紐づくセッション情報が複数存在します。メニュー画面の表示処理( menu.php )において、 session_start 関数を呼び出すことで、このセッション情報の一覧の中から送信されたセッションID( PHPSESSID )に紐づく1件のセッション情報を識別できるようになります。このようにして $_SESSION 変数が利用できるようになります。

まとめ

  • 一般的にセッションはCookieを使って実装されている
  • Cookieはクライアント(Webブラウザ)上に少量のデータを保存する仕組み
  • PHPはセッションを開始するとCookieにセッションIDを保存し、セッションに保存したデータそのものはサーバサイドに保存する