php クッキーとセッション

2013年11月17日

クッキーとセッションに関するメモ。

クッキー

クッキー Cookie
Web サーバーから送信したデータを Web ブラウザに保存するための仕組み。テキストデータをユーザーのブラウザに保存することができ、ブラウザに保存されたデータは、次回のリクエスト時に Web サーバに自動的に送信される。
  • クッキーとは、クライアント側に保存可能な小さなテキスト
  • クッキーで管理されたデータは、クライアント側で自由に削除したり改ざんしたりすることが可能なので、クッキー情報を元にアプリケーション全体の挙動を左右するような判定を行うのは危険
  • 実データがネットワーク上を流れるので、通信系路上にリクエスト情報をロギングするような通信機器やソフトウェアがある場合は、クッキー情報が漏洩する可能性がある。
  • クッキーをクライアントに保存するにはsetcookie関数を使用する。

setcookie()

PHPでWebブラウザにデータを保存する(クッキーを送信する)場合は、setcookie()関数を使う。

bool setcookie ( string $name , string $value , int $expire , string $path , string $domain )

  • クッキーを送信する
  • string $name:クッキーの名前
  • string $value:クッキーの値。この値はクライアントのコンピュータに保存されるので、 重要な情報は格納してはならない。 name が ‘cookiename’ だとすると、 その値は $_COOKIE[‘cookiename’] で取得することができる。
  • int $expire: クッキーの有効期限。これは Unix タイムスタンプなので Epoch(1970 年 1 月 1 日)からの経過秒数。 time() 関数により 返された現在のUNIX標準時に、期限としたい必要な秒数を加算したものを 利用することができる。 time()+60*60*24*30 はクッキーの有効期限を 30 日後にセット。 0 を設定したり省略したりした場合は、クッキーはセッションの最後 (つまりブラウザを閉じるとき) が有効期限となる。
  • string $path:サーバー上での、クッキーを有効としたいパス ‘/’ をセットすると、クッキーは domain 配下の全てで有効となる。 ‘/foo/’ をセットすると、クッキーは /foo/ ディレクトリとそのサブディレクトリ配下 (例えば /foo/bar/) で有効となる。 デフォルト値は、クッキーがセットされたときのカレントディレクトリ。
  • string $domain:クッキーが有効なドメイン。
  • 戻り値:もしもこの関数をコールする前に何らかの出力がある場合には、 setcookie() は失敗し FALSE を返す。 setcookie() が正常に実行されると、TRUE を返す。 この関数では、ユーザーがクッキーを受け入れたかどうかを判断することはできない。

setcookie() は、その他のヘッダ情報と共に 送信するクッキーを定義する。 ほかのヘッダ情報と同様に、 クッキーは、スクリプトによる他のあらゆる出力よりも前に 送信される必要がある(これはHTTPプロトコルの制約)。 <html> や <head> タグはもちろん 空白も含め、あらゆる出力よりも前にこの関数をコールするようにしなければならない。

つまり、setcookie()関数が含まれる「<?php」タグの前に、HTMLタグやHTMLコメント、文字あるいは空白を書いてしまうと「Warning … headers already sent by」というエラーが表示され、クッキーは送信されない。

  • 一度クッキーが送信されると、次のページのロードからは $_COOKIE や $HTTP_COOKIE_VARS 配列によってクッキーにアクセスできる。
  • クッキーの値は $_REQUEST 配列からもアクセスできる。

(注意点)

  • 大きなデータは保存できない。(4kbまで)
  • 悪意のあるユーザはクッキーの値を変更できるので、重要な情報は保存してはならない。
  • クッキーのデータはブラウザを操作すれば簡単に見えてしまい、また、ウィルスによりクッキーのデータが漏洩する可能性もあるので、秘密情報(パスワードなど)を保存してはならない。

クッキーの受信

Web ブラウザに保存されたクッキーは、有効期限内であれば、リクエスト時にブラウザからサーバへ送信される。

送信されたクッキーの値は、スーパーグローバル変数「$_COOKIE」に代入される。例えばクッキー名が「foo」の値を利用するには「$_COOKIE[‘foo’]」とする。

クッキーを使った簡単なカウンターの例

<?php
if(!isset($_COOKIE['count'])){
  $count = 1;    //初回のアクセス
}else{
  $count = $_COOKIE['count'] + 1;    //2回目以降のアクセス
}
setcookie('count', $count);    
//クッキーを発行(送信)setcookie ($name , $value)
?>  
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Cookie Counter</title>
</head>
<body>
<?php
echo 'アクセス回数: ' . $count;
?> 
</body>
</html>

クッキーの削除

クッキーを削除するには、有効期限を過去に設定する。

setcookie(‘name’, ”, time() – 3600);

引数の順序は名前、値、有効期限なので、値を省略する場合は空文字(”)とする必要がある。

time() – 3600は現在のタイムスタンプから60×60(1時間)引いているので1時間前。特に3600に意味はない。(過去に設定すればいつでも可)

time()
現在の Unix タイムスタンプを返す

セッション

HTTP は1回毎のリクエストが独立していて、通常は同じクライアントからのアクセスかどうかを判別できない。セッションは同じクライアントからの一連のアクセうかどうかを見分ける方法の1つ。ページ遷移を超えて変数を保持できる「セッション変数」と呼ばれる変数も用意されている。

  • セッションのデータはサーバ側で保存される
  • ネットワーク上を流れるのはセッションIDのみ
  • セッションはセッション変数($_SESSION)にデータを格納し、PHPコードからセッション変数のデータにアクセス可能
  • 複数のページやスクリプトから使用できる
  • セッション変数はいつでも削除できるので、ログアウトの機能も提供可能
  • 但し有効期限がなく、セッションの終了(ブラウザを閉じたとき)と同時に自動的に削除される
  • セッションの開始はsession_start()関数で行う
  • セッションが始まると、セッションIDがセットされ、セッションを一意に識別できる
  • セッションIDは、ブラウザを閉じるか、session_destroy()が呼び出されると削除されるが、セッション変数は削除されない
  • セッション変数を効率的に破壊するには$_SESSIONに空の配列をセットする
  • ブラウザがクッキーを許可している場合、セッションはクッキーを一時的なセッションIDの格納領域として使用している可能性があるので、PHPを使ってセッションを完全に閉じるにはこのクッキーも削除しなければならない

セッションとクッキーの違い

セッションは、ユーザを識別する「セッションID]とWebサーバにデータを保存する「セッション変数」により実現される。

クッキーはデータをWebブラウザに保存するが、セッションはデータ(セッション変数)をWebサーバ上に保存し、セッションIDだけをクッキーに保存する。

セッションの利用

bool session_start ()
新しいセッションを開始、あるいは既存のセッションを再開する。
session_start() は、セッションを作成、 もしくは、リクエスト上で GET, POST またはクッキーにより渡されたセッション ID に基づき現在のセッションを復帰する。この関数が呼び出されると、関数は、既にセッションが存在するかどうかをセッションIDの有無で判断する。まだセッションがなければ新しいセッションIDを作り、それ以降同じアプリケーションから呼び出されると既存のセッションと認識されセッションを再開する。
戻り値: セッションが正常に開始した場合に TRUE、それ以外の場合に FALSE を返す

session_start()関数は、必ず、Webブラウザへの出力が行われる前に、呼び出す必要がある。(setcookie()関数と同様、HTTPプロトコルの制約)

session_start()関数を呼び出した後は、セッション変数「$_SESSION」が使えるようになり、データを保存することができる。セッション変数は、セッションを終了するまでページを移動しても利用することが可能。

session_start()関数はセッションを開始するが、データは何もセットされないのでセッション変数($_SESSION)にデータを格納する。

標準ではセッション変数は、セッションファイルに保存され、保存場所はphp.iniの「session.save_path」で指定されている。

session_start();
$_SESSION['username'] = 'mdavis';

セッションの利用例

セッションを使った簡単なカウンタの例

<?php  
session_start();
?>  
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Session Counter</title>
</head>
<body>
<?php
if(!isset($_SESSION['count'])){
  $_SESSION['count'] = 1;    //初回のアクセス
}else{
  $_SESSION['count'] ++;    //2回目以降のアクセス
}
echo 'アクセス回数: ' . $_SESSION['count'];
?> 
</body>
</html>

セッションを閉じる

session_destroy()関数をつかってセッションを破壊しても、セッション変数は削除されないので、空の配列をセットして削除する。またクッキーを一時的なセッションIDの格納領域としている可能性があるので、そのクッキーも削除する必要がある。

$_SESSION = array();
    if(isset($_COOKIE[ session_name()])){
      setcookie(session_name(), '', time() - 3600);
    }
    session_destroy();

セッションがクッキーを使ってセッションIDを保存している場合、そのIDはセッションの名前を持つクッキーに保存されている。セッションの名前はsession_name()で取得できる

session_name ([ string $name ] )
現在のセッション名を返す。 name を渡すと、 session_name() はセッション名を上書きして元のセッション名を返す。
session_destroy()
現在のセッションに 関連づけられたすべてのデータを破棄する。この関数は、 セッションに関するグローバル変数を破棄しない。 また、セッションクッキーを破棄しない。
ユーザーがログアウトするときのように、セッションを切断するには、 セッション ID の割り当ても解除する必要がある。セッション ID の受け渡しに クッキーが使用されている場合(デフォルト)には、セッションクッキーも 削除されなければない。 そのためには setcookie() が利用できる。