HTTP State Management Mechanism
Network Working Group D. Kristol
Request for Comments: 2109 Bell Laboratories, Lucent Technologies
Category: Standards Track L. Montulli
Netscape Communications
February 1997
HTTP State Management Mechanism
【この記述の状態】
このドキュメントはインターネットコミュニティに対するインターネット
スタンダードトラックプロトコルを記述し、改善のための論議と提案を要求
する。標準化状態とこのプロトコルの状態のため "Internet Official
Protocol Standards" (STD 1) の最新版を参照してください。この記述の配
布は無制限である。
【1. 概要】
このドキュメントは HTTP リクエストとレスポンスに関する状態付きセッ
ションを構築する方法を詳述する。これは Cookie と Set-Cookie という二
つの新しいヘッダについて説明し、セッションに携わっているオリジンサー
バとユーザエージェントの間で状態情報を運搬する。ここで記述されている
方法は Netscape の Cookie 提案と異なっているが、Netscape の方法を使
用する HTTP/1.0 ユーザエージェントと相互操作する事ができる (履歴の章
参照)。
【2. 用語】
ユーザエージェント、クライアント、サーバ、プロキシ、オリジンサーバと
いう用語は HTTP/1.0 仕様におけるものと同じ意味を持つ。
完全に的確なホスト名 (FQHN: fully-qualified host name) はホストの完
全に的確なドメイン名 (FQDN: fully-qualified domain name) (i.e., .com
や .uk のようなトップレベルドメイン名で終わっている、完全に記述され
たドメイン名) か、ホストのインターネットプロトコル (IP) 数値アドレス
のどちらかを意味する。完全に的確なドメイン名がより好まれる; 数値の
IP アドレスは推奨されない。
リクエストホストとリクエスト URI と言う用語は、そのクライアントが
(ポートではないが) ホストとしてサーバに送る値と、HTTP リクエスト行の
absoluteURI (http_URL) の abs_path の一部の値をそれぞれ表している。
リクエストホストは FQHN でなければならない事に注意。
ホスト名は IP アドレスか FQHN 文字列のいずれかで記述する事ができる。
しばしばわれわれはあるホスト名と別のホスト名を比較する。以下の条件が
成り立つならホスト A の名前とホスト B の名前はドメイン一致する。
* 両方のホスト名が IP アドレスであり、それらのホスト名文字列が正確に
一致する; もしくは
* 両方のホスト名が FQDN 文字列であり、それらのホスト名文字列が正確に
一致する; もしくは
* A が FQDN 文字列であり、NB と言う形態を持っている。ここで N は空で
ない名前文字列である。B は .B' と言う形態を持ち、B' は FQDN 文字列
である (x.y.com は .y.com とドメイン一致するが y.com とは一致しな
い)。
ドメイン一致は可逆操作でない事に注意: a.b.c.com は .c.com とドメイン
一致するが、逆は成り立たない。
Netscape 元々の状態管理実装で使用されていたため、われわれはオリジン
サーバとユーザエージェント間で受け渡しされ、ユーザエージェントによっ
て保存される状態情報を表すためクッキーと言う用語を使用する。
【3. 状態とセッション】
このドキュメントは HTTP リクエストとレスポンスで状態のあるセッション
を構築するための方法を詳述する。現在、HTTP サーバはそれぞれのクライ
アントリクエストを直前もしくは続きのリクエストと関連付ける事なく応答
している; 技術的にはわれわれが "セッション" と呼んでいる、多数の前後
関係を持つ HTTP リクエストやレスポンスを評価するための状態情報を交換
する事を望んでいるクライアントとサーバを認めている。この前後関係は、
たとえばユーザ選択が購入を行う前に集計できる "ショッピングカート" や
ユーザの直前の購読が販売を表すような週刊誌閲覧システムを構築するため
に使われるだろう。
もちろん、多くの異なる潜在的な前後関係が存在し、したがって多くの異な
るセッションの潜在的なタイプが存在する。クッキーの交換によって構築さ
れるセッションのための設計者の理論的枠組みは以下のキー属性を持ってい
る。
1.それぞれのセッションは始めと終わりを持つ。
2.それぞれのセッションは比較的短い期間を持つ。
3.ユーザエージェントかオリジンサーバのどちらかがセッションを終了す
る事ができる。
4.セッションは状態情報の交換を暗に含んでいる。
【4. 概略】
ここで、オリジンサーバがユーザエージェントに状態情報を送信し、ユーザ
エージェントがオリジンサーバに状態情報を返す方法を概説する。目的は
HTTP とユーザエージェントへの影響を最小限に押さえる事である。セッ
ションを維持する必要のあるオリジンサーバのみが重要な影響を受け、サー
バがより高級な状態管理サポートを供給していなければ、この影響は主に
Common Gateway Interface (CGI) プログラムに限定できる (下記の実装考
察参照)。
4.1 構文: 一般
Set-Cookie と Cookie と言う二つの状態管理ヘッダは attribute-value ペ
アを含んでいる統語上の共通特性を持っている。以下の文法は HTTP/1.1 仕
様 [RFC 2068] から表記法と DIGIT (10 進数字) トークンと token (略式
に、非特殊、非空白文字のシーケンス) を使用している。
av-pairs = av-pair *(";" av-pair)
av-pair = attr ["=" value] ; オプション値
attr = token
value = word
word = token | quoted-string
属性 (names) (attr) は大文字と小文字を区別しない。空白の存在は token
の中で許されている。上記の構文記述はオプションとしての値を表している
一方で、ほとんどの場合それらに attr を必要とする事に注意。
[注意]: 上記の構文は属性と = 記号の間に空白を認めている。
4.2 オリジンサーバの役割
4.2.1 一般
もしオリジンサーバが初期化を望めば、オリジンサーバはセッションを初期
化する (ここの "セッション" は永続的なネットワーク接続を表しているの
ではなく、HTTP リクエストとレスポンスから構築される論理的なセッショ
ンを表している事に注意。永続的接続が存在するかどうかはクッキーでもた
らされるセッションの使用に何の影響も持たない)。セッションを初期化す
るため、オリジンサーバはクライアントに Set-Cookie と言う特別なレスポ
ンスヘッダを返す (詳細は後述)。
もしユーザエージェントがセッションを続ける事を選択すれば、ユーザエー
ジェントはオリジンサーバに Cookie リクエストヘッダ (後記参照) を返す。
オリジンサーバはそれを無視する事もできるし、そのセッションの現在の状
態を決定するために使う事もできる。オリジンサーバはクライアントにまっ
たく同じ情報や異なる情報の付いた Set-Cookie レスポンスヘッダを送り返
す事ができるし、Set-Cookie ヘッダをまったく送らない事もできる。オリ
ジンサーバは Max-Age=0 付きの Set-Cookie ヘッダをクライアントに送る
事によりセッションを有効に終了する。
サーバはどのようなレスポンスに対しても Set-Cookie レスポンスヘッダを
返す事ができる。ユーザエージェントは Cookie リクエストヘッダを送るべ
きであり、リクエストごとに下記に詳述される別のルールに従うべきである。
オリジンサーバは一つのレスポンスに複数の Set-Cookie ヘッダを含む事が
できる。介在するゲートウェイがこのような複数ヘッダを単一のヘッダに折
りたたむ事ができる事に注意。
4.2.2 Set-Cookie 構文
Set-Cookie レスポンスヘッダに対する構文は:
set-cookie = "Set-Cookie:" cookies
cookies = 1#cookie
cookie = NAME "=" VALUE *(";" cookie-av)
NAME = attr
VALUE = value
cookie-av = "Comment" "=" value
| "Domain" "=" value
| "Max-Age" "=" value
| "Path" "=" value
| "Secure"
| "Version" "=" 1*DIGIT
口語で表すと、Set-Cookie レスポンスヘッダはコンマで区切られた一つ以
上のクッキーのリストが続く Set-Cookie: トークンを含む。それぞれの
クッキーはセミコロンで区切られた 0 個以上の attribute-value ペアを伴
う NAME=VALUE ペアから開始する。attribute-value ペアに対するこの構文
は初期に示された。具体的な attribute とそれらの値の意味は以下に記述
する。NAME=VALUE attirbute-value ペアはそれぞれのクッキーの最初に来
なければならない。もし与えられるなら、その他の属性はどのような順番で
も存在できる。もし属性が一つのクッキーに対して一回以上現れるなら、動
作は未定義である。
NAME=VALUE
必須。状態情報 ("cookie") の名前は NAME であり、その値は VALUE で
ある。$ から開始する NAME はその他の使用のため予約され、アプリケー
ションは使用してはならない。
VALUE はユーザエージェントに対する非空白文字列であり、ひょっとする
とサーバで選択された印字可能な ASCII エンコーディングが行われた、
オリジンサーバが送る事を選択したどんなものでもありうる。"非空白文
字列" の内容はオリジンサーバのみが重要であり関連している事を暗に意
味している。事実、内容は Set-Cookie ヘッダを調べるどんなものによっ
ても読めるだろう。
Comment=comment
オプション。クッキーはユーザに関するプライベートな情報を含む事がで
きるため、Cookie 属性はオリジンサーバが意図したクッキーの使用をド
キュメントする事を認める。ユーザはこのクッキーのセッションを初期化
するか続けるかを決定するため、この情報を調べる事ができる。
Domain=domain
オプション。Domain 属性はクッキーが有効なドメインを指定する。明白
に指定されたドメインは常にドットから始まらなければならない。
Max-Age=delta-seconds
オプション。Max-Age 属性はクッキーの寿命を秒単位で定義する。
delta-seconds 値は 10 進数の正数である。delta-seconds 秒の経過後、
クライアントはクッキーを破棄すべきである。ゼロ値はクッキーがすぐに
破棄されるべきである事を意味する。
Path=path
オプション。Path 属性はこのクッキーを適用する URL のサブセットを指
定する。
Secure
オプション。(値の伴わない) Secure 属性は、ユーザエージェントがこの
クッキーを送り返す時はいつでも安全な方法 (指定はない) でオリジン
サーバに接続する場合のみ使用される。
(ひょっとするとユーザの制御下に置かれている) ユーザエージェントは
"secure" クッキーに対して妥当と考えられるセキュリティレベルを決定
する事ができる。Secure 属性は、クッキー内容を保護するためのセッショ
ンの重要性を示す事を、サーバからユーザエージェントにセキュリティア
ドバイスとして検討させるべきである。
Version=version
必須。10 進数整数値の Version 属性はこのクッキーが対応している状態
管理仕様のバージョンを示している。この仕様に対して、Version=1 が適
用される。
4.2.3 キャッシュ制御
オリジンサーバは返すリソースと Set-Cookie ヘッダの両方のキャッシュの
可能性の影響を意識すべきである。"public" ドキュメントのキャッシュは
望ましい。たとえば、もしオリジンサーバが Set-Cookie レスポンスヘッダ
を生成しなければならないページに対してセッションの開始を示すための見
張りとして、"front door" ページのような公開ドキュメントを使用するな
ら、そのページはオリジンサーバが以後のリクエストを参照するために
"pre-expired" キャッシュを保存すべきである。セッションに厳密に非公開
な情報を含んでいるような "private document" は共有キャッシュにキャッ
シュされるべきではない。
もしクッキーが単一のユーザによって使用されるのを意図しているなら、
Set-Cookie ヘッダはキャッシュされるべきではない。複数のユーザによっ
て共有される事が意図されている Set-Cookie ヘッダはキャッシュ可能であ
る。
オリジンサーバは状況に応じて以下の追加的な HTTP/1.1 レスポンスヘッダ
を送るべきである:
* Cache-control: no-cache="set-cookie"
(Set-Cookie ヘッダのキャッシュを隠蔽するため)
そして以下の一つ:
* Cache-control: private
(共有キャッシュから非公開ドキュメントのキャッシュを隠蔽するため)
* Cache-control: must-revalidate
(ドキュメントのキャッシュを有効にし、それをクライアントに返す前に
再確認が必要である事を示すため)
* Cache-control: proxy-revalidate
(ドキュメントのキャッシュを有効にするが、(ユーザエージェントではな
く) プロキシキャッシュがそれをクライアントに返す前にその正当性の再
確認が必要である事を示すため)
* Cache-control: max-age=0
(ドキュメントのキャッシュを有効にし、(それを "pre-expiring" によっ
て) それをクライアントに返す前に再確認が必要である事を示すため。す
べてのキャッシュはそれぞれの場合にドキュメントを再確認しないだろう)
HTTP/1.1 サーバは、下りストリームに HTTP/1.0 プロキシが存在しない事
を確証できなければ、Set-Cookie レスポンスヘッダを含んでいるレスポン
スに対して Expires: old-date (old-date は過去の時間である) を送らな
ければならない。HTTP/1.1 サーバは、Expires: old-date ディレクティブ
に加えて HTTP/1.1 プロキシによるキャッシュを許すために別の
Cache-Control ディレクティブを送る事ができる; Cache-Control ディレク
ティブは HTTP/1.1 プロキシよって Expires: old-date をオーバーライド
するだろう。
4.3 ユーザエージェントの役割
4.3.1 Set-Cookie の解釈
ユーザエージェントはそれぞれの (名前もしくは IP アドレスとポートに
よって区別される) オリジンサーバから Set-Cookie レスポンスヘッダ経由
で渡される状態情報の分割トラックを維持する。ユーザエージェントは指定
がなければ以下のデフォルトオプション属性値を適用する:
Version 元々 Netscape によって定義された "old cookie" の動作
をデフォルトとする。
Domain リクエストホストをデフォルトとする (リクエストホストの開始に
ドットが存在しない事に注意)。
Max-Age デフォルトの動作はユーザエージェントが終了した時にクッキーを
破棄するものとする。
Path Set-Cookie レスポンスを生成した、最上位が / であるがそれを含
んでいないリクエスト URL のパスとして定義する。
Secure もし存在しなければ、ユーザエージェントは安全でないチャンネル
上でクッキーを送る事ができる。
4.3.2 クッキーの拒絶
可能性のあるセキュリティやプライバシー違反を妨げるため、もし以下のい
ずれかが真であるなら、ユーザエージェントはクッキーを拒絶する (その情
報を保存しないだろう):
* Path 属性の値がリクエスト URI のプレフィクスでない。
* Domain 属性の値が埋め込まれたドットを含んでいなかったり、一つのドッ
トで開始していない。
* リクエストホストの値が Domain 属性とドメイン一致しなかった場合。
* リクエストホストが (IP アドレスではなく) FQDN であり、HD 形式を
持っている。ここで D は Doman 属性の値であり、H は一つ以上のドット
を含んだ文字列である。
例:
* Domain=.foo.com に対するリクエストホスト x.y.foo.com からの
Set-Cookie は拒否される。これは H が y.x でありドットを含んでいる
ためである。
* Domain=.foo.com に対するリクエストホスト x.foo.com からの
Set-Cookie は受け入れられる。
* Domain=.com や Domain=.com. を持つ Set-Cookie は常に拒否される。
これは値に埋め込まれたドットが存在しないためである。
[訳注: 埋め込まれたドットとは、文字列の先頭や終端でない場所に存在
するドット]
* Domain=ajax.com を持つ Set-Cookie は拒否される。これは Domain 値が
ドットから開始していないためである。
4.3.3 クッキー管理
もしユーザエージェントが、NAME が既に存在するクッキーと一致し、Domain
と Path 属性値が正確に (文字列レベルで) 一致する Set-Cookie リクエス
トヘッダを受信したなら、新しいクッキーは古い物に取って代わる。しかし
ながら、もし Set-Cookie が Max-Age の値として 0 を持っているなら、
そのクッキーは (新しい物も古い物も) 破棄される。そうでなければ、クッ
キーはそれらが破棄される時間までの期間 (リソースが許せば) 蓄積する。
ユーザエージェントがクッキーを保存しておく有限の空間を持っているため、
それぞれのオリジンサーバが設定したクッキーの最大個数の制限に従って、
たとえば、least-recently-used アルゴリズムを使用して、新しいクッキー
のための空間を確保するため古いものから破棄する事もできる。
もし Set-Cookie レスポンスヘッダが Comment 属性を含んでいるなら、ユー
ザエージェントはクッキーに可読形式でその情報を保存すべきであり、クッ
キー検査のためのユーザインターフェースの一部としてコメントテキストを
表示すべきである。
ユーザエージェントはユーザにクッキー削除の制御を可能にすべきである。
まれに使用されるクッキーはネットワークアプリケーションに対して "設定
ファイル" として機能し、ユーザはもしそれが least-recently-used クッ
キーであったとしてもそれを保存する事を望む事ができる。ある可能な実装
は、チェックボックスを通してクッキーの恒久的な保存 (もしくは逆に即時
削除) を可能なインターフェースであろう。
プライバシー考察ではユーザがクッキー管理上の重要な制御をもつ事を指示
している。プライバシーの章はより多くの情報を含んでいる。
4.3.4 オリジンサーバへのクッキー送信
オリジンサーバにリクエストを送る時、ユーザエージェントはもし以下に基
づいたリクエストに適用できるクッキーを持っているなら、オリジンサーバ
に Cookie リクエストヘッダを送信する。
* リクエストホスト
* リクエスト URI
* クッキーの寿命
ヘッダに対する構文は:
cookie = "Cookie:" cookie-version
1*((";" | ",") cookie-value)
cookie-value = NAME "=" VALUE [";" path] [";" domain]
cookie-version = "$Version" "=" value
NAME = attr
VALUE = value
path = "$Path" "=" value
domain = "$Domain" "=" value
cookie-version 属性値は、Set-Cookie レスポンスヘッダの Version 属性
に相当する値でなければならない。そうでなければ、cookie-version は 0
である。path 属性値は Set-Cookie レスポンスヘッダの Path 属性に相当
する値でなければならない。そうでなければ、この属性は Cookie リクエス
トヘッダから除外されるべきである。domain 属性値は Set-Cookie レスポ
ンスヘッダの Domain 属性に相当する値でなければならない。そうでなけれ
ば、この属性値は Cookie リクエストヘッダから除外されるべきである。
Set-Cookie レスポンスヘッダの Cookie 属性に相当する Cookie リクエス
トヘッダの属性は存在しない事に注意。ユーザエージェントはオリジンサー
バにコメント情報を返さない。
以下のルールはユーザエージェントが持っているすべてのクッキーの一つか
ら適用可能な cookie-value を選択するために利用できる。
Domain 選択
オリジンサーバの完全に的確なホスト名はクッキーの Domain 属性とド
メイン一致しなければならない。
Path 選択
クッキーの Path 属性はリクエスト URI のプレフィクスと一致しなけ
ればならない。
Max-Age 選択
無効になったクッキーは破棄されるべきであり、したがってオリジン
サーバに転送されない。
もし複数のクッキーが上記の基準を満たしていれば、それらは Cookie ヘッ
ダの中に、より詳細な Path 属性が先に来るように順番に存在する。他の属
性 (e.g., Domain) に関係する順序付けは定義しない。
[注意]: 過去の互換性のため、Cookie ヘッダのセパレータはどこでもセミ
コロン (;) である。サーバは将来の互換性のため cookie-value を区切る
コンマ (,) も受け入れるべきである。
4.3.5 証明できないトランザクションにおけるクッキー送信
ユーザはプライバシーを保証するためにセッション上で制御を持たなければ
ならない (下記プライバシーの章参照)。しかしながら、実装を単純化する
ためと、十分な安全保護機能がある複雑なレイヤーを追加する事を防ぐため、
このドキュメントは証明できるトランザクションと証明できないトランザク
ションとを区別する。もしユーザがトランザクションにおける Cookie の使
用に先立って、リクエスト URI を再検査するためのオプションを持つなら、
トランザクションは証明できる。もしユーザがそのオプションを持たなけれ
ば証明できないトランザクションである。典型的に証明できないトランザク
ションは、ユーザエージェントが自動的にインライン化されたり埋め込まれ
たりしたエンティティを要求する時や、オリジンサーバからのリダイレク
ション (3xx) レスポンスを解決する時に起こる。典型的に、ユーザが示した
元々のトランザクションは証明でき、そのトランザクションはユーザエージェ
ントを証明できないトランザクションを作るよう直接もしくは間接的に誘引
するだろう。
これが証明できないトランザクションをもたらす時、証明できないトランザ
クションのリクエスト URI のホスト名が D とドメイン一致するようなドメ
イン属性 D 付きクッキーが、その元のトランザクションに対して送信もし
くは受信された時にのみ、ユーザエージェントはセッションを有効にしなけ
ればならない。
この制限は、悪意のあるサービス製作者が別のドメインのサーバのセッショ
ンをユーザエージェントに開始したり続行させるための証明できないトラン
ザクションを使う事を妨げる。このようなセッションの開始や続行はプライ
バシーの期待に反し、セキュリティ問題ともなりうる。
ユーザエージェントは、ユーザエージェントやユーザエージェントが実行す
るオートマトンプログラムが上記のルールを無視できるような、デフォルト
が "off" になっている設定可能なオプションを提供する事ができる。
多くの現在使用されているユーザエージェントは、多くのリンクを証明でき
るように提示する再検査オプションを既に供給している。実例を挙げると、
いくつかのユーザエージェントはマウスポインタがそのリンク上に置かれた
時に詳細なリンクとして参照されている URL を表示する。それゆえ、ユー
ザはブラウザに表示させる前にそのサイトを訪れるかどうかを決定する事が
できる。(しかし現在使用されているユーザエージェントは実装されていな
い。似たような技術はフォームをサブミットするために使用されるボタンに
対して使用されている -- ユーザエージェントはもしユーザがこのボタンを
選択したなら実行されるためのアクションを表示できる)。しかしながら、
これがすべてのリンクを証明できるようにするわけではない; たとえば、自
動的にロードされる画像へのリンクは、通常 "マウスポインタ" 証明を受け
ない。
多くのユーザエージェントは、ユーザがドキュメントの HTML ソースを表示
したり、別のアプリケーションによって表示するため外部ファイルにソース
を保存するためのオプションも供給している。そのようなオプションが未完
全な再確認メカニズムを供給している一方で、いくつかのユーザエージェン
トはこの意図のためそれを受け入れ可能とみなさないようにしている。
4.4 オリジンサーバの Cookie ヘッダの解釈方法
ユーザエージェントは、Path 属性が新しいリクエストのそれと一致した時、
オリジンサーバに Set-Cookie ヘッダの情報よりも多い情報を送り返してく
る。Cookie ヘッダを受信した時、オリジンサーバは隣接するクッキーに対
する属性として、特にプレフィクスが $ をもつ NAME の付いたクッキーを
扱うべきである。そのような NAME の値は、辞書的に (左から右に) $ プレ
フィクスを持っていない名前のもっとも近くのクッキーに適用するものとし
て解釈される。もし直前のクッキーが存在しなければ、値は全体としての
クッキーメカニズムに適用される。たとえば、以下のクッキーを考慮する。
Cookie: $Version="1"; Customer="WILE_E_COYOTE";
$Path="/acme"
$Version は全体としてクッキーメカニズムに適用される (そしてそのクッ
キーメカニズムに対するバージョン番号を与える)。$Path は値 (/acme) が
Customer クッキーが Set-Cookie レスポンスヘッダで定義される時に使用
される Path 属性を定義する。
4.5 キャッシュプロキシの役割
URL とドキュメント内容の両方から状態情報を分離する理由は、そのキャッ
シュ許可を容易にするためである。クッキーをサポートするため、キャッ
シュプロキシは HTTP 仕様のこれらのルールに従わなければならない:
* 可能であれば、キャッシュ確証ルールに基づいてキャッシュからのリクエ
ストを優先する。
* プロキシが他のサーバを使わなければならないすべてのリクエストで
Cookie リクエストヘッダをいっしょに渡す。
* クライアントにレスポンスを返す。すべての Set-Cookie ヘッダを含む。
* Expires, Cache-control: no-cache, Cache-control: private のような、
通常のヘッダの制御に従って受信したレスポンスをキャッシュする。
* Cache-control: no-cache="set-cookie" のように、通常のヘッダの制御
に従い Set-Cookie をキャッシュする (Set-Cookie ヘッダは大抵キャッ
シュされるべきではない)。
プロキシはプロキシレスポンス (リクエスト) においてそれら自身の
Set-Cookie (Cookie) ヘッダを導入してはならない。
【5. 例】
5.1 例 1
リクエストやレスポンスヘッダの最細部は除外されている。ユーザエージェ
ントがクッキーを保存していない事を仮定する。
1. ユーザエージェント -> サーバ
POST /acme/login HTTP/1.1
[フォームデータ]
ユーザはフォームを使用して識別を行う。
2. サーバ -> ユーザエージェント
HTTP/1.1 200 OK
Set-Cookie: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"
クッキーはユーザの身元を反映している。
3. ユーザエージェント -> サーバ
POST /acme/pickitem HTTP/1.1
Cookie: $Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme"
[フォームデータ]
ユーザは "ショッピングバスケット" に品目を選択する。
4. サーバ -> ユーザエージェント
HTTP/1.1 200 OK
Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";
Path="/acme"
ショッピングバスケットは品目を含む。
5. ユーザエージェント -> サーバ
POST /acme/shipping HTTP/1.1
Cookie: $Version="1";
Customer="WILE_E_COYOTE"; $Path="/acme";
Part_Number="Rocket_Launcher_0001"; $Path="/acme"
[フォームデータ]
ユーザはフォームから配送方法を選択する。
6. サーバ -> ユーザエージェント
HTTP/1.1 200 OK
Set-Cookie: Shipping="FedEx"; Version="1"; Path="/acme"
新しいクッキーは配送方法を表している。
7. ユーザエージェント -> サーバ
POST /acme/process HTTP/1.1
Cookie: $Version="1";
Customer="WILE_E_COYOTE"; $Path="/acme";
Part_Number="Rocket_Launcher_0001"; $Path="/acme";
Shipping="FedEx"; $Path="/acme"
[フォームデータ]
ユーザは注文の処理を選択する。
8. サーバ -> ユーザエージェント
HTTP/1.1 200 OK
トランザクションは完結する。
新しいクッキーを受信する時々の後、ユーザエージェントはオリジンサーバ
上にリクエストの一連性を作る。すべてのクッキーは同じ Path 属性と (デ
フォルト) ドメインを持つ。リクエスト URL のすべてがプレフィクスとし
て /acme を持ち、Path 属性と一致するため、それぞれのリクエストはそれ
までに受信したすべてのクッキーを含んでいる。
5.2 例 2
この例は Path 属性の効果を例証する。リクエストとレスポンスヘッダの詳
細部はすべて除外されている。ユーザエージェントはクッキーを持っていな
いと仮定する。
以前のリクエストに対するレスポンスで、ユーザエージェントが以下のレス
ポンスヘッダを受信していると想像する。
Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";
Path="/acme"
Set-Cookie: Part_Number="Riding_Rocket_0023"; Version="1";
Path="/acme/ammo"
ユーザエージェントによる /acme/ammo/... 形式の URL に対する (同じ)
サーバへのリクエストの続きは以下のようなリクエストヘッダで示される:
Cookie: $Version="1";
Part_Number="Riding_Rocket_0023"; $Path="/acme/ammo";
Part_Number="Rocket_Launcher_0001"; $Path="/acme"
より詳細な Path 属性 /acme/ammo 付きのクッキーに対する NAME=VALUE ペ
アが、比較して詳細でない Path 属性 /acme より前に来る事に注意。さら
に、同じクッキー名が一度以上現れる事にも注意。
ユーザエージェントによる /acme/parts/ 形式の URL に対する (同じ)
サーバへのリクエストの続きは以下のようなリクエストヘッダで示される:
Cookie: $Version="1"; Part_Number="Rocket_Launcher_0001"; $Path="/acme"
ここで、二番目のクッキーの Path 属性 /acme/ammo はリクエスト URL
/acme/parts のプレフィクスではないため、クッキーはサーバに送信されな
い。
【6. 実装考察】
ここでわれわれは状態管理を実装するオリジンサーバに対する有望で望まし
い推測を行う。
6.1 Set-Cookie 内容
オリジンサーバの内容は、多分状態情報の使用を必要とするいくつかのアプ
リケーション領域から外れた所に分割されるはずである。アプリケーション
領域はそれらのリクエスト URL によって区別できる。Set-Cookie ヘッダは
それぞれの領域に対して Path 属性を設定する事で、アプリケーション領域
に関する情報と結合することができる。
セッション情報は状態を表現するテキストを明らかに明瞭もしくは符号化さ
せる。しかしながら、もし長くなりすぎれば、扱いにくくなるだろう。それ
ゆえ、実装者はサーバ側リソースのキーとなるセッション情報を選択しても
良い。もちろん、データベースの使用はこの状態管理仕様が避けるくらい不
可解ないくつかの問題を発生する。すなわち:
1.サーバ側に本当の状態を保持する
2.たとえば、ユーザエージェントが終了によりセッションを終わる場合の
ように、データベースエンティティをどのように、いつガーベッジコレ
クションするか
6.2 状態のないページ
キャッシュは WWW のスケーラビリティに利益を与える。そのため、本来的
に状態が埋め込まれたドキュメントの数を減少させる事は重要である。たと
えば、もしショッピングバスケット形式のアプリケーションがそれぞれの
ページでユーザの現在のバスケットの内容を常に表示するなら、それらの
ページはキャッシュされず、したがってそれぞれのユーザのバスケットの内
容は異なるだろう。言い換えれば、もしそれぞれのページが "ショッピング
バスケットの内容を見る" というリンクを含んでいれば、そのページは
キャッシュされる。
6.3 実装制限
実用的なユーザエージェント実装はそれらが保存できるクッキーのサイズや
数に制限を持つ。一般的に、ユーザエージェントのクッキーサポートは固定
した制限を持つべきではない。それらは可能な限り頻繁に使用されるクッキー
を保存するよう努めるべきである。さらに、一般使用のユーザエージェント
は個々に以下の最小容量を用意すべきであるが、すべて必要と言うわけでは
ない。
* 最低 300 個のクッキー
* 一つのクッキーあたり最低 4096 バイト (Set-Cookie ヘッダの構文記
述での非末期クッキーを構成する文字列のサイズによる評価)
* 個々のホストもしくはドメイン名ごとに最低 20 個のクッキー
特定の目的もしくは制限された容量のデバイスに対して造り出されたユーザ
エージェントはユーザがセッションベースのオリジンサーバと相互に作用す
る事を保証するため、最低 4096 バイトの 20 クッキーを用意すべきである。
Set-Cookie レスポンスヘッダの情報はその完全体を保持しなければならな
い。もしクッキーを保存するために不十分な空間であるというような理由が
あれば、それは先頭を断ち切らずに破棄されなければならない。
アプリケーションは可能な限り少なく、小さなクッキーを使用すべきであり、
クッキーの損失に潔くうまく対処すべきである。
6.3.1 サービスアタックの拒否
ユーザエージェントは与えられたホストもしくはドメイン名から保存される
クッキーの数やクッキー情報のサイズの上限を設定する事を選択できる。そ
うでなければ、悪意のあるサーバは肯定的レスポンスとともにユーザエー
ジェントを多数のクッキーや巨大なクッキーであふれさせようとする事がで
き、ユーザエージェントが他のサーバから受け取ったクッキーを強制的に消
すだろう。しかしながら、それでも上記に記述されている最小限度はサポー
トされるべきである。
【7. プライバシー】
7.1 ユーザエージェント制御
オリジンサーバはサーバを通してユーザの経路を追跡するために Set-Cookie
ヘッダを構築する事ができる。ユーザは、たとえ彼らの身元が明白でない場
合でも、情報の邪魔な蓄積の動作に反対できる (身元はユーザが後に確認情
報を含むフォームを送信してから明白になるだろう)。このため、この状態
管理仕様は、ユーザにこの制御を与えるためのインターフェースを詳述しな
いままだが、ユーザエージェントがユーザにこのような可能な侵入を制御さ
せる事を必要とする。しかしながら、供給される制御メカニズムはユーザに
最低以下の事を許可するべきである。
* クッキーの送信と保存を完全に無効にする事
* 状態のあるセッションが進行中であるかどうかを決定する事
* そのクッキーの Domain 属性の基準上のクッキーの保存を制御する事
そのような制御は、たとえば以下のようなメカニズムによって供給できる。
* ユーザエージェントがオリジンサーバにクッキーを送ろうとしている時、
ユーザにセッションを開始しないオプションを提供する事を通知する。
* 状態のあるセッションが進行中である事を可視的な指示を表示する。
* ユーザがウィンドウやユーザエージェントセッションを終了する時、
クッキーを保存するかどうかをユーザに決めさせる。
* どんな時もクッキーの内容をユーザに調べさせる。
ユーザエージェントは通常状態情報を記憶しないで実行開始する。ユーザ
エージェントを決して Cookie ヘッダを送信しないように設定する事が可能
である。この場合、オリジンサーバの状態を維持する事はできない (この時
ユーザエージェントは Set-Cookie レスポンスヘッダを処理する方法を知ら
ないように振る舞うだろう)。
ユーザエージェントが実行を終了した時、ユーザにすべての状態情報を破棄
させるべきである。あるいは、ユーザエージェントは状態情報が維持される
べきかどうかをユーザに問い合わせる事もできる; デフォルトは "no" とな
るべきである。もしユーザが状態情報を維持する事を望めば、次回ユーザ
エージェントが実行される時に回復されるだろう。
[注意]: おそらくユーザエージェントは長期間クッキーを保存するためファ
イルを使用する事に注意深くあるべきである。もしユーザがユーザエージェ
ントの一つ以上のインスタンスを実行するなら、クッキーは混合されるか、
そうでなければ失敗する。
7.2 プロトコルデザイン
Domain 属性の値の制限や証明できないトランザクションに関するルールは
クッキーが "悪い" サイトに "漏れる" 方法を減らす事に十分でない。意図
は悪いサイトや関係する閉じたホストのセットへのクッキーを制限する事で
ある。このため、リクエストホストは Domain に対して設定できる値に制限
される。われわれはホスト host1.foo.com と host2.foo.com に対して共有
クッキーを受け入できる事を考慮するが、a.com と b.com は対象外である。
同様に、一つのサーバはクッキーに対してリクエスト URI と関連する Path
のみを設定する事ができる。
【8. セキュリティ考察】
8.1 クリアテキスト
Set-Cookie や Cookie ヘッダの情報は保護されていない。二つの重要な影
響は:
1.それらで伝えられるすべての慎重な情報は進入者達にさらされる。
2.悪意のある仲介者は、このヘッダが別の場所に転送されるような予期でき
ない変更を行う事ができる。
これらの事実は、人や金銭的な情報が安全なチャンネル上でのみ送信される
べきである事を意味している。慎重な情報を減らすためや、ヘッダの内容が
データベースのキーである時、オリジンサーバは失敗の原因から不正な
Cookie の値を防ぐ事を絶えず注意すべきである。
8.2 クッキー偽造
正確なアプリケーションデザインは関連するドメインからの偽造アタックを
避ける事ができる。考慮すると:
1.ユーザエージェントは victim.cracker.edu へのリクエストを制作し、
クッキー session_id="1234" を受け取ってデフォルトのドメイン名を
victim.cracker.edu に設定する。
2.ユーザエージェントは spoof.cracker.edu へのリクエストを制作し、
Domain=".cracker.edu" の付随するクッキー session-id="1111" を受け
取る。
3.ユーザーエージェントは再度 victim.cracker.edu へのリクエストを制作
し、以下のクッキーを渡す。
Cookie: $Version="1";
session_id="1234";
session_id="1111"; $Domain=".cracker.edu"
victim.cracker.edu は、二番目のクッキーの Domain 属性が自身に対す
るものではなく、無視すべき事に注意して、そのクッキーをもたらしたの
が自身でない事を検出すべきである。
8.3 予想外のクッキー共有
ユーザエージェントは、それぞれの試行ごとに異なるドメインとなるホスト
間のセッション情報の共有の防御を行うべきである。特に埋め込まれたりイ
ンライン化されているオブジェクトは、それらが本質的に異なるホストの間
のクッキーを共有するために使用されるなら、サーバプライバシー問題を引
き起こす事が可能である。たとえば、悪意のあるサーバはホスト b.com 上
の CGI に対する URI でホスト a.com に対するクッキー情報を埋め込む事
ができる。ユーザエージェント実装者は、可能な限りこのような交換を妨げ
る事を強く推奨される。
【9. その他の類似提案】
三つの事なる案が類似した目的を成し遂げるために行われてきた。この仕様
は Kristol の State-Info 提案と Netscape の Cookie 提案の混合である。
Brain Behlendorf は、ユーザエージェントが初期化し、"クリック痕跡" を
追跡するためのオリジンサーバによって使用される Session-ID ヘッダを提
案した。しかしながら、これはオリジンサーバが定義したどんな状態をも運
搬しない。Phillip Hallam-Baker は類似した目的のため別のクライアント
定義セッション ID メカニズムを提案している。
セッション ID とクッキーの両方が状態のあるセッションを維持するための
方法を供給する一方で、それらの意図する目的は異なり、その結果、それら
に対するプライバシー要求が異なっている。それらを使用してサーバが過程
の追跡を行えるように、もしくは共有マシーンで複数のユーザを区別できる
ように、ユーザがセッション ID を初期化する。クッキーはサーバによって
初期化され、ここで述べられているクッキーメカニズムはユーザの自覚なし
に別の方法で置き換えられる何かの制御をユーザに与える。さらに、セッ
ション ID がユーザ選択の簡単な情報しか含まないのに対して、クッキーは
豊富なサーバ選択情報を伝える。
【10. 履歴】
10.1 Netscape 実装との互換性
HTTP/1.0 クライアントとサーバは Netscape の元のクッキー提案を反映し
た Set-Cookie と Cookie ヘッダを使う事ができる。これらは "古い" そし
て "新しい" クッキーの間で互換性のある操作をカバーしている事に注意。
10.1.1 拡張された Cookie ヘッダ
この提案は互換性のある方法で Cookie リクエストヘッダに attribute-value
ペアを追加する。"新しい" クッキーを受け取った "古い" クライアントは
理解できない属性を無視するだろう; オリジンサーバに理解したものを返す。
"新しい" クライアントは常に新しい形式でクッキーを送る。
"新しい" クッキーを受け取った "古い" サーバは $ で開始している名前を
持つたくさんのクッキーが存在するように見え、それらを無視するだろう
("古い" サーバはコンマでなくセミコロンで区切られているこれらのクッ
キーを期待する)。"新しい" サーバは $Version 属性の欠落によって、"古
い" クライアントから送られてきたクッキーを検出する事ができる。
10.1.2 Expires と Max-Age
Netscape の元の提案は、Max-Age の代わりに固定長変化フォーマットの日
付値を取る Expires ヘッダを定義していた:
Wdy, DD-Mon-YY HH:MM:SS GMT
Expires 日付フォーマットは埋め込まれた空白を含み、"古い" クッキーは
値の前後に引用符を持っていない事に注意。この使用を実装するクライアン
トは "古い" クッキーと Expires を認識すべきである。
10.1.3 区切り文字
Netscape の元の提案において、attribute-value ペアは " 引用文字列を受
け付けない。オリジンサーバは、受け取り側ユーザエージェントがそれら
(i.e., "新しい" クッキー) を理解できるか分からなければ、引用符が必要
な値を送る事に注意すべきである。("新しい") ユーザエージェントは、クッ
キーのバージョンがこの仕様やその後の仕様にすべて順応している時のみ、
Cookie ヘッダに引用符で囲んだ値を使用すべきである。
Netscape の元の提案において、attribute-value ペアを分割する = 前後に
空白を認めていない。それゆえ、このような空白は新しい実装に注意して使
用されるべきである。
10.2 キャッシュと HTTP/1.0
HTTP/1.0 にしたがっているいくつかのキャッシュは、HTTP/1.1 に先立って
ヘッダのキャッシュを抑制するためのメカニズムが存在しないため、必然的
に Set-Cookie ヘッダをキャッシュするだろう。このキャッシュはセキュリ
ティ問題を引き起こす事ができる。オリジンサーバにより Set-Cookie を
伴って転送されたドキュメントは常にキャッシュ不能であるか "pre-expired"
となるだろう。キャッシュが (Expires: <過去の日時> や Pragma: no-cache
(HTTP/1.0) や Cache-control: no-cache (HTTP/1.1) を伴う) ドキュメント
をキャッシュしない指示に従う限り、キャッシュできないドキュメントは問
題とならない。しかしながら、期限の切れたドキュメントはキャッシュに保
存されるかもしれない。それらは新しいリクエストごとに再確証 (条件付き
GET) を必要とするが、いくつかのキャッシュ操作機能はそれらのキャッシュ
のルールにルーズであり、しばしばそれらを最初に確証する事なく期限の切
れたドキュメントを送付する。この要因の組み合わせはあるユーザに意味の
あるクッキーを後に別のユーザに送る事を導く事ができる。ドキュメントは
古く (期限切れ) なっているが、Set-Cookie ヘッダはキャッシュに保存さ
れ、キャッシュはキャッシュされているヘッダを含めて後のリクエストに対
するレスポンスとしてドキュメントを返す。
【11. 謝辞】
This document really represents the collective efforts of the
following people, in addition to the authors: Roy Fielding, Marc
Hedlund, Ted Hardie, Koen Holtman, Shel Kaphan, Rohit Khare.
【12. 著者のアドレス】
12. AUTHORS' ADDRESSES
David M. Kristol
Bell Laboratories, Lucent Technologies
600 Mountain Ave. Room 2A-227
Murray Hill, NJ 07974
Phone: (908) 582-2250
Fax: (908) 582-5809
EMail: dmk@bell-labs.com
Lou Montulli
Netscape Communications Corp.
501 E. Middlefield Rd.
Mountain View, CA 94043
Phone: (415) 528-2600
EMail: montulli@netscape.com