備忘録的プログラミングリファレンス

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などに編集します。

http ヘッダ例
print "Content-type: text/html\n";
print "Set-Cookie:user_id=1a0ec;max-age=3600;path=/~user/test;SameSite=Strict;\n";
print "\n";

 http ヘッダでは、変数と変数の間にスペースを入れないようにします。エラーの原因になることがあります。

 以下のように変数と変数の間にスペースを入れないようにしましょう。

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 = "~";
クッキーの設定( id が example で有効期間が3時間)
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によって取得することもできます。

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 にします。

http ヘッダによる削除例
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);