セッション管理

HTTP通信

前回はGETメソッドやPOSTメソッドでデータを送信して、PHPプログラムで処理する基本的な方法を見てきました。リクエストやレスポンス時のデータにはヘッダー情報として色々な値が格納されています。今回はリクエストやレスポンス時のヘッダー情報を取得し、リクエストヘッダーの中身を指定して別々のページへリダイレクトさせる方法を見ていきます。そしてセッション管理について学びましょう。

セッション管理とは

HTTP通信は、一度リクエストを送信するとレスポンスが返ってきたときに通信処理が終わりますので通信状態を維持できません。それなら会員ページなどの情報を使用するwebアプリケーションでは、情報を持ち続けてHTTP通信するのは無理じゃないのかと思うかもしれませんが、擬似的に通信状態を維持するためのセッションと呼ばれる仕組みがあります。
Cookieというものを聞いたことがあると思います。Cookieはクライアント側に保存される比較的軽量なデータで、このCookieを便利にしたのがセッションです。

サーバーはクライアントのCookieを読み取ることで、操作するユーザー専用のページやより適したページを表示することができます。クライアントからのリクエストによって処理した内容をサーバーに保存しておき、クライアントを識別するための固有のデータをCookieに保存します。次アクセスした時、そのデータを参照してサーバーに保存したデータを読み出すようにするのがセッション管理の仕組みであります。

今回はセッションについて学び、多数のユーザがアクセスする Webアプリケーションで、1人1人のユーザを区別できるようになりましょう。

$_SERVERにはヘッダー情報が格納されている

$_SERVERというグローバル変数には、ヘッダー情報の個々のデータを「フィールド:値」というペアで扱います。そしてフィールドにはリクエストヘッダーとレスポンスヘッダー専用のものがあり、必要に応じてエンティティヘッダーや一般ヘッダーのフィールドが追加されます。

それぞれ以下のようなフィールドがあります。厳密にはそれぞれもっとありますがとりあえず覚えるのは下の一覧でいいです。

リクエストヘッダーフィールド内容
Hostリクエスト先のサーバー
User-Agentブラウザの情報
Accept利用可能なアプリケーションやメディアタイプ
Accept-Languageクライアントが利用可能な言語
Accept-Encoding利用可能なエンコーディング形式
Accept-Charset利用可能な文字セット
Referer直前にリンクされていたURL
Cookieクライアントに保存されているクッキーデータ
レスポンスヘッダーフィールド内容
Locationリダイレクト先のURL
Serverサーバーアプリケーションの種類
WWW-Authenticateクライアントに認証を要求
ETagリソースを特定するための情報、エンティティタグ
エンティティヘッダーフィールド内容
Content-Typeリソースのタイプ
Content-Encodingリソースコンテンツのエンコード方法
Content-Lengthコンテンツのサイズ
Expiresコンテンツの有効期限
Last-Modifiedコンテンツの最終更新日時
一般ヘッダーのフィールド内容
Cache-Controlキャッシュの取り扱い指示や情報
Connection接続の永続性情報
Dateコンテンツの作成日時
Transfer-Encodingコンテンツの転送エンコーディング方式

フィールドをズラーッと書いていきましたが、$_SERVERにリクエストとレスポンスの両方が格納されているので、区別するために別のキー名がつけられています。そのため上記のフィールド名ではなくそれぞれに付けられた別のキー名を用いて情報を扱う必要があります。詳しくはそれぞれの説明で。

リクエストからヘッダー情報を取得し、表示

実際にリクエストヘッダーの情報を表示するプログラムを作成してどんな情報があるか見てみましょう。百聞は一見にしかず、プログラムを動かして覚えましょう。

<!DOCTYPE html>
<html>
<head>
<title> requestheader </title>
</head>
<body>
<?php require_once 'Esc.php';  //前に作ったプログラムのままで
foreach($_SERVER as $key => $val) {//配列でデータがあるのでforeach文で全部取り出す
    if(mb_strpos($key, 'HTTP_') === 0) { //「HTTP_」という文字列が先頭にある場合
        esc($key);
        print ' : ';
        esc($val);
        print '<br>';
    }
}
?>
</body>
</html>

表示してみると色々な情報を持っていることがわかりましたね。
上記のプログラムの説明として、まずmb_strpos()関数は文字列の中に指定した文字列が最初にある場所を返します。上では$keyにキー名が入っているので、キー名に’HTTP_’という文字列がどこに入っているか調べています。なぜこのように調べているかといいますと、リクエストヘッダーのフィールドのキー名は先頭に「HTTP_」が付くからです。そして表示したページをよく見ると①全て大文字になっている②「-」が「_」となっていることに気づきましたでしょうか。ヘッダーフィールドはこのようにキー名を別につけられているのです。なのでUser-Agentは「HTTP_USER_AGENT」となります。

レスポンスヘッダーに独自に設定する

サーバーからレスポンスを返す場合自動的にサーバーアプリケーションが設定して返しますが、header()でヘッダー情報を設定することができます。

Locationフィールドでリダイレクトさせる

レスポンスヘッダーのLocationというフィールドを使って遷移先のURLを設定することで、クライアントを設定したURLへ移動させることができます。
header()関数を使ってLocationフィールドにURLを設定してみます。header()関数の決まりは、実行前にHTMLのタグやreuire_once()などの関数でファイルを読み込むなどしてはいけません。header()関数を使用する時は一番初めに記述しましょう。

<?php
header('Location: http://localhost/phppractice/send.php/');
?>

毎回URLを記述するのは面倒なので、$_SERVERを利用してパスを取得してURLを指定しましょう。

<?php
header('Location: http://'. $_SERVER['HTTP_HOST']. dirname($_SERVER['SCRIPT_NAME']). '/send.php');
?>

$_SERVER[‘HTTP_HOST’]でサーバーのホスト名、dirname($_SERVER[‘SCRIPT_NAME’])でサーバー内部のパスを取得しています。dirname()関数でPHPファイルの、ファイル名を含まないパスを取得するようにしています。dirname()関数は親ディレクトリのパスを返します。

Cookieにユーザーのパソコンにwebデータを保存する

Cookieはユーザーの操作を支援するためにあり、初めてアクセスしたWebサイトからコンピュータに小さなファイルで、個々を識別する情報などが書き込まれ、そのデータはクライアント側に保管します。この情報でアプリケーション側がユーザーがどんなユーザーなのかを判断したり、閲覧記録からユーザーに適したコンテンツを表示することができます。

cookieを発行する

クライアントがアクセスしたらsetcookie()関数を使用してクライアントのパソコンに保存します。
setcookie()関数はパラメーターが多いですが、ひとまず3つパラメーターを設定します。

<?php
setcookie('name', '佐藤',  time() + 600);//
?>

‘name’はCookieの名前、’佐藤’は保存する値、time() + 600はCookieの有効期限です。有効期限は1970年1月1日からの経過秒数で指定するもので、time()で標準時刻から現在までの秒数を取得して+600で10分プラスしているので、有効期限が10分になります。

Cookieの値を表示してみます。

<?php
print $_COOKIE['name'];
?>

1度 setCookie.phpにアクセスしてからshowCookie.phpにアクセスしてみてください。

設定されたCookieの中身が表示されましたね。基本的にこのようにCookieの中身を設定します。

2回目以降のアクセス時にユーザー名を表示する

初回のアクセス時にユーザー名を登録し、2回目以降Cookieの有効期限内ではユーザー名を表示するようにします。Cookieにユーザー名が設定されている場合入力を促し、既に設定されている場合はユーザー名を表示する、というプログラムを作成しましょう。

<!DOCTYPE html>
<html>
<head>
<title> setNameCookie </title>
</head>
<body>
<?php
require_once 'Esc.php';
?>
<?php if(isset($_COOKIE["name"])) :?>
<p>こんにちは、<?php print esc($_COOKIE["name"]); ?>さん!</p>
<?php else : ?>
<form method="POST" action="setCookie2.php">
お名前:
<input type="text" name="name">
<input type="submit" value="送信" />
</form>
<?php endif; ?>
</body>
</html>

名前が設定されていない場合、送信ボタンを押した時に入力されている名前を登録するためのプログラムを作成します。

<?php
setcookie('name', $_POST['name'],  time() + 60);
print "名前の登録が完了しました";
?>

初回は何も設定されていないので入力画面になります。名前を入力して送信してみます。

Cookieに名前を登録できたはずですので、もう一度setNameCookie.phpを表示してみます。

初回では入力画面でしたが、登録した後は挨拶文に変わりましたね。このようにユーザー情報があるかないかで表示するHTMLを変更します。

セッションで通信状態を維持する

HTTP通信は一度リクエストを送信したらレスポンスが返された時点で通信処理が終了するので通信状態を維持することはできませんが、維持しているように見せかけるセッションという仕組みを利用します。

セッションのデータはサーバー側に保存される

Cookieはクライアントに保存されるのと異なり、セッションのデータはサーバー側に保存されます。サーバー側にはクライアントを識別するIDが保存され、CookieにもIDが保存されます。2回目以降のアクセスではこのIDを参照してサーバー側に保存されたデータを読み込みます。

Cookieだけでなくセッションも利用する理由は以下の通りです。

  • CookieはHTTPのヘッダー情報を利用するので、第三者がその通信経路の中でヘッダー情報を収集していれば、中身を見れるので危険です。
  • Cookieはクライアント側に保存されるのでデータを改ざんすることができ、大切なデータを扱うのには危険です。

セッションを使って入力データを保持する

セッションを利用するにはまずsession_start()関数を使います。新しいセッションを開始、または既存のセッションを再開することができ、正常に開始できればTRUE、それ以外はFALSEを返します。また、setcookie()関数と同じく、ブラウザにデータを表示する前に呼び出さなければいけません。

セッションにデータを保存するページを作成します。

<!DOCTYPE html>
<html>
<head>
<title> setNameSession </title>
</head>
<body>
<?php
require_once 'Esc.php';
session_start();
?>
<?php if(isset($_SESSION["name"])) :?>
<p>こんにちは、<?php print esc($_SESSION["name"]); ?>さん!</p>
<?php else : ?>
<form method="POST" action="setSession.php">
お名前:
<input type="text" name="name">
<input type="submit" value="送信" />
</form>
<?php endif; ?>
</body>
</html>

Cookieの時と同じようにセッションに保存するプログラムを作成します。

<?php
session_start();
$_SESSION['name'] = $_POST['name'];
print 'セッション情報保存完了';
?>

Cookieの時と同じく名前がセッションに保存されていない時は入力画面が表示され、登録した2回目以降は名前が表示されたかと思います。Cookieと違うところは、データはサーバー側に保存されることで、セッション開始時にIDが生成され保存される。そしてそのIDを頼りにユーザー情報を読み込み、今回では名前を$_SESSION[“name”]のように利用しております。

使い終わったら切断しましょう

ブラウザを閉じればセッションは終了されますが、切断されていません。つまり、サーバー側のセッション用のふぁいるやセッションIDを割り当てるためのクライアント側のCookieが残ります。$_SESSION変数で参照していたデータもメモリ上に残っています。

それらを破棄するための処理を行っていきます。$_SESSION変数を空にする、Cookieを空にする、セッションを破棄します。そのためのプログラムは以下の通りです。

<?php
session_start();//sessionを再開
$_SESSION = array();//空にする
if(isset($_COOKIE[session_name()])){
  setcookie(session_name(), '', time() - 3600, '/');//cookieを空にする
}
session_destroy();//セッションを破棄する
?>

セッションが不要になるのはいつ?

セッションを切断をするタイミングは、例えばユーザー情報を登録するページが複数ページあり、最終的に登録が終わった時、データベースにこれらのユーザーの情報が登録されているのでこの時点でセッションで保持しているデータが不要になります。このように、登録が完了するまではセッションで保持して、戻るボタンを押してしまったり次の入力する画面に遷移する時などにセッションデータを利用し、登録完了して不要になれば破棄すれば良いと思います。

コメント

タイトルとURLをコピーしました