Cookie について
Cookie とは?
Cookie とは、ウェブサイトがあなたのウェブブラウザに保存する小さなデータのことです。
基本的には、サーバーは誰が通信しているのかを特定できません。Cookie に保存されたユーザー ID などを利用することで、サーバーはあなたを識別できるようにすることができます。
Cookie について
Cookie の仕組みと役割
Cookie に保存された情報は、ウェブサイトの閲覧中(セッション)か、あらかじめ設定された期間にわたって保持されます。これにより、オンラインストアでの買い物かごの内容を記録したり、前回のウェブページの続きから操作を再開したりすることが可能になります。
このように、現在の状態を記録し、セッションの内容を保持できる方式を ステートフル といいます。
Cookie のデータは、サーバーから HTTP ヘッダの一部としてブラウザに送られ、ブラウザはそれを受け取って保存します。
Cookie の特徴と有効期限
Cookie には有効期限を設定できます。有効期限が設定されている場合、その期間内はブラウザに保存され続けます。有効期限が設定されていない場合は、ブラウザを閉じると同時に削除されます。
Cookie の主な特徴は以下の通りです。
- クライアント(ブラウザ)またはサーバーに保存され、ステートフル なサービスを可能にします。
- HTTP ヘッダ に含まれて送受信されます。
- 有効期限が設定されていればその期間保存され、設定されていなければブラウザの終了時に削除されます。
- サイズは通常 4KB までで、1つのサーバーにつき最大20個、合計で300個まで保存できます。
- 有効期限を設定しない Cookie は「セッション Cookie」と呼ばれ、ブラウザを閉じると削除されます。
JavaScript と Cookie
JavaScript で作成された Cookie は、通常、サーバーとの通信では利用されず、ブラウザ内で使われることが前提となります。
JavaScript で作成された Cookie は、有効期限を指定しない場合、セッションが終了するまで(ブラウザを閉じるまで)保持されます。
セッション
という言葉について
セッション
とは、ブラウザがリクエストを送信し、サーバーがレスポンスを返す一連の通信単位を指します。多くの場合、ブラウザを閉じるまでの期間や、サーバーとブラウザ間の通信自体を指します。
誤解されがちですが、Cookie にユーザーを特定するための仮 ID を記録し、実際の ID を隠蔽する方法を「セッション」と表現するのは適切ではありません。
Cookie 以外の記録方法
Cookie にはセキュリティ上の問題や、保存できる容量が小さいという欠点があります。これらの問題を解決するために、Web Storage と呼ばれる別のクライアント側の一時記録方法も利用されています。
記録された Cookie の確認方法
ブラウザに記録されている Cookie は確認することや削除することができます。
例えば Google Chrome では、メニュー
→ その他のツール
→ デベロッパー ツール
で開発用ツールを開く。
開発ツールのタブメニューでApplication
の左に表示される縦メニューの Storage のCookie
を開いてください。
該当するドメイン名からそのドメイン名で保存されているクッキーが表示されます。
Cookie の記録方法
ブラウザ上に Cookie を記録させる方法にはいくつかあります。http ヘッダデータ、HTMLタグ、JavaScritと使った方法があります。
サーバーと Cookie をやり取りするなら、http ヘッダデータを利用します。HTMLタグ、JavaScrit を使った方法はブラウザ内で Cookie を利用する方法に限られます。
http ヘッダ
CGIなどに編集します。
print "Content-type: text/html\n"; print "Set-Cookie:user_id=1a0ec;max-age=3600;path=/~user/test;SameSite=Strict;\n"; print "\n";
http ヘッダでは、変数と変数の間にスペースを入れないようにします。エラーの原因になることがあります。
以下のように変数と変数の間にスペースを入れないようにしましょう。
print "Content-type: text/html\n"; print "Set-Cookie: user_id=1a0ec;max-age=3600; path=/~user/test;SameSite=Strict;\n"; print "\n";
HTMLタグで
<meta http-equiv="Set-Cookie" content="~">
Javascript
document.cookie = "~";
document.cookie = "id=example;max-age=10800;"
Cookieの値
"~"の内容は、以下のようにします。
NAME=値;expires=値;domain=値;path=値;secure
| パラメータ | 意味 |
|---|---|
| NAME=値 | Cookie を個々に識別するための名称とその値。NAME は任意で必須、値は空もあり。名称は制御文字、空白、タブ、()<>@,;:\"/[]?={}を除いたASCII文字。
値に日本語がある場合はとくにURLエンコードをした方がよい。 要件が満たされた値によってはURLエンコード、デコードすると思ったものと違うときがある。 |
| expires=値 | Cookie の有効期限。非推奨。
Wed, 1-Jan-2020 00:00:00 GMT有効期限が過ぎるとCookieを削除する。 |
| Max-Age=値 | Cookie の有効期限、秒数で指定。ゼロまたは負の値は直ちに期限切れに。ExpiresとMax-Ageの両方が設定されたら、Max-Ageを優先。 |
| domain=値 | Cookieの有効なドメインの範囲。省略した場合はCookieを発行したホストのドメン(www.***.comなど)になります。 |
| path=値 | Cookieの有効なパス(URL)の範囲。省略した場合はCookieを発行したパスになる。 |
| secure | SSL 通信時のみ有効になる。URL が HTTPS となる場合に有効。HTTP ではやりとり不可となる。 |
| HttpOnly | HTTP での通信で Cookie が有効。これが有効にならないと、上記の secure は反映されない。 |
| sameSite=[ 'Strict' | 'Lax' | 'None' ] | 他のサイトでの Cookie の利用範囲。
'Strict' が指定されたクッキーは他のサイトで利用できない。 'Lax' は GET を利用時は他のサイトでもクッキーが利用できる。POST は不可。 'None'は従来どおりで規制がない。 |
Set-Cookie:NAME="value";expires=Wed, 1-Jan-2020 00:00:00 GMT;domain=www.***.com;path=/;secure
書き込みや読み込み時には、エンコードやデコードが必要になる場合があります。
Cookieの取得方法
Cookie はサーバーで利用されることが前提であるため、サーバー上の CGI などで取得する方法を利用します。
CGIなど
print "$ENV{'HTTP_COOKIE'}\n";
JavaScript
JavaScriptによって取得することもできます。
document.cookie
値については、「Cookie の値」を参照のこと。
Cookieの削除方法
Cookieの削除は、有効期間 Max-Age 値を 0、または有効期限 expires 値を過去の日付にします。 ここでは、JavaScriptによって削除する方法を紹介します。
JavaScript
document.cookie = "クッキーの名称(NAME)=; max-age=0;"
document.cookie = "id=; max-age=0;"
document.cookie = "クッキーの名称=; expires='1970-12-31T23:59:59Z';"
値については、「Cookieの値」を参照のこと。
ただし注意点があります。クッキーを個別化する、最初の NAME の他に domain や path といった値が一致していないと同じクッキーとは見なされません。
JavaScript からは、SameSite の値が 'None' でなければ値の変更ができないようです。
http ヘッダによる Cookie の削除
http ヘッダを使用する方法は、Cookie の記録方法と同じです。
削除の場合は、http ヘッダで有効期限 expires 値を過去に設定するか、または有効期間 Max-Age 値を 0 にします。
print "Content-type: text/html\n";
print "Set-Cookie:user_id=1a0ec;expires=Thu, 1-Jan-1970 00:00:00 GMT;path=/~user/test;SameSite=Strict;\n";
print "\n";
有効期限 expires 値を過去に指定する方法は、ブラウザによって即時に実行されない場合もあります。
エンコードとデコード
Cookieはどのサーバーでも参照できるようにするためにMIME形式で保存することが望ましいです。
いろいろな環境下で読み書きが行われる場合には、記録時にはエンコード、読み込み時にはデコードする必要があります。
Perlなど
エンコード
$xx =~ s/(\W)/sprintf("%%X", unpack("C", $1))/eg;
デコード
$xx =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("C", hex($1))/eg;
JavaScript
エンコード
xx = escape(xx);
デコード
xx = unescape(xx);
