Cookie

◆ Cookieとは

掲示板にアクセスする際に、前回入力した自分のログイン名が自動的に入力されている、そんなことを実現するのが クッキーCookie)です。ページを表示する際にサーバーからこっそり Cookie 情報と呼ばれるデータが送信されてクライアント側のディスクに保存され、次回そのページを表示する際に、ブラウザが Cookie 情報を送り返します。

◆ Cookieの詳細(設定時)

Cookie データはサーバーからクライアントに返される HTTP レスポンスのヘッダに含まれます。形式は以下の通りです。

Set-Cookie: LOGIN=tanaka; expires=Thu, 1-Jan-2030 00:00:00 GMT;

LOGIN=tanaka の部分は AGE=26 でも PASSWORD=hi.mi.tu でも、好きな変数名と値を指定することができます。expires にはブラウザが Cookie情報を覚えておく期限を指定します。タイムゾーンは必ず GMT(世界標準時)で指定してください。expires を省略すると、ブラウザが終了するまで覚えておきます。

◆ Cookieの詳細(保存時)

ブラウザは、サーバーから受け取った Cookie 情報をメモリやディスクに保存しておきます。Windows XP + Internet Explorer の場合は、下記のフォルダに保存されるようです。expires 指定が無い場合は、メモリにだけ保存します。

C:\Document and Setting\ログイン名\Cookies
◆ Cookieの詳細(送信時)

ブラウザは、次回、同じページ、あるいは、同じフォルダにある別ページにアクセスする際に、覚えておいた Cookie 情報を HTTP リクエストのヘッダに含めて送信します。

Cookie: LOGIN=tanaka

これをサーバーが受け取ることにより、その日初めてアクセスしたページであっても、前回のログイン名を表示することができるようになります。

■ Cookie情報を書き込む

◆ Cookie情報を書き込む

クライアント側に Cookie 情報を送り込むには、下記のような CGI を作成します。記号や日本語などのデータは URLエンコード形式 などにエンコードしておきます。$setcookie は、HTTP のヘッダ部(Content-type: の前後、最初の空行よりも前)に記述してください。

cookie1.cgi
#!/usr/local/bin/perl

# Cookie 情報書き込み用のヘッダを生成する
$setcookie = SetCookie("LOGIN", "tanaka", "p");

# Cookie情報書き込み用ヘッダを作成する
# SetCookie(名前, 値, モード)
# モード:p=パーマネント=永続的設定
#         t=テンポラリ=ブラウザを終了するまで有効
sub SetCookie {
    local($name, $value, $mode) = @_;
    local($tmp);
    $value =~ s/(\W)/sprintf("%%%02X", unpack("C", $1))/eg;
    $tmp = "Set-Cookie: $name=$value;";
    if ($mode eq "p") {
        return "$tmp; expires=Thu, 1-Jan-2030 00:00:00 GMT;";
    } else {
        return "$tmp";
    }
}

# ページを書き出す
print <<END_OF_DATA;
Content-type: text/html
$setcookie

<html>
<head><title>Cookie情報の設定</title></head>
<body>
<div>Cookie情報を設定しました。</div>
<div>setcookie = [ $setcookie ]</div>
</body>
</html>
END_OF_DATA

■ Cookie情報を読み込む

◆ Cookie情報を読み込む

クライアント側に書き込んだ Cookie 情報を読み込むには、CGI に次のような機能を埋め込みます。

cookie2.cgi
#!/usr/local/bin/perl

# Cookie情報を読み出す
GetCookie(*COOKIE);

# Cookieデータを解釈する
sub GetCookie {
    local(*COOKIE) = @_;
    local($name, $value);
    foreach (split(/; */, $ENV{'HTTP_COOKIE'})) {
        ($name, $value) = split(/=/);
        $value =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("C", hex($1))/eg;
        $COOKIE{$name} = $value;
    }
}

# ページを書き出す
print <<END_OF_DATA;
Content-type: text/html

<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">
<title>Cookie情報の読み出し</title>
</head>
<body>
<hr>
<div>Cookie情報を読み出しました。</div>
<div>LOGIN = [ $COOKIE{'LOGIN'} ]</div>
<hr>
</body>
</html>
END_OF_DATA

読み込んだ Cookie 情報は $COOKIE{変数名} という連想配列に格納されます。

■ Cookie情報を削除する

◆ Cookie情報を削除する

クライアント側に書き込んだ Cookie 情報を削除するには、expires に過去の時刻を指定した Set-Cookie ヘッダを送ります。

cookie3.cgi
#!/usr/local/bin/perl

# Cookie情報を削除するヘッダ
$delcookie = DelCookie("LOGIN");

# Cookieデータを削除する
sub DelCookie {
    local($name) = @_;
    return "Set-Cookie: $name=; expires=Thu, 1-Jan-1970 00:00:00 GMT;";
}

# ページを書き出す
print <<END_OF_DATA;
Content-type: text/html
$delcookie

<html>
<head>
<title>Cookie情報の削除</title>
</head>
<body>
<hr>
<div>Cookie情報を削除しました。</div>
<hr>
</body>
</html>
END_OF_DATA
注意

Cookie のテストを行う際は、ブラウザのキャッシュに注意してください。ブラウザがキャッシュデータを表示してしまい、設定したはずの Cookie 情報が表示されなかったり、削除したはずの Cookie 情報が表示されたように見えてしまう場合があります。キャッシュを抑制するには「CGIの結果がキャッシュされないようにする」を参照してください。

■ 複数のCookie情報を書き込む

◆ 複数の Cookie情報を書き込む

一度に複数の Cookie 情報を書き込むには、下記のように複数の Cookie ヘッダを設定してください。

$setcookie1 = SetCookie("LOGIN", "tanaka");
$setcookie2 = SetCookie("AGE", "26");

print <<END_OF_DATA;
Content-type: text/html
$setcookie1
$setcookie2

<html>
   :

読み込み側はこれらの値を $COOKIE{'LOGIN'} と $COOKIE{'AGE'} で参照することができます。

■ Cookieの期限を1週間にするには

◆ Cookieの期限を設定する

1週間だけ有効な Cookie 情報を設定するには、Set-Cookie ヘッダの expires に 1週間後の日時を指定します。"Thu, 1-Jan-2030 00:00:00 GMT" の代わりに、以下のサブルーチンで得られる日時を指定してください。

$expires = getExpiresTime(7);
sub getExpiresTime {
    local($days) = @_;
    local(@mon) = ( "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" );
    local(@wday) = ( "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" );
    local($time, $sec, $min, $hour, $mday, $mon, $year, $wday);

    $time = time() + ($days * 24 * 60 * 60);
    ($sec, $min, $hour, $mday, $mon, $year, $wday) = gmtime($time);
    return sprintf("%s, %d-%s-%d %02d:%02d:%02d GMT",
      $wday[$wday], $mday, $mon[$mon], $year + 1900, $hour, $min, $sec);
}

Copyright (C) 2002 杜甫々