Studying HTTP > RFC-Translations related HTTP

この文書は、 D. Kristol, L. Montulli: HTTP State Management Mechanism (RFC 2965), October 2000. を 橋本英彦 が日本語訳した物です。 この文書の取り扱いについては、[Studying HTTP] の RFC 日本語訳を利用するにあたってに従って下さい。


Network Working Group
Request for Comments: 2965
Obsoletes: 2109
Category: Standards Track
                             D. Kristol
 Bell Laboratories, Lucent Technologies
                            L. Montulli
                     Epinions.com, Inc.
                           October 2000

HTTP 状態管理メカニズム

この文書の位置付け

この文書は、インターネットコミュニティにおけるインターネット標準化過程プロトコルを規定し、改良のために議論と提案を求めるものである。 このプロトコルの標準化状態と状況については、"Internet Official ProtocolStandards" (STD 1) の最新版を参照していただきたい。 この文書の配布に制限は無い。

著作権表示

Copyright © The Internet Society (2000). All Rights Reserved.

IESG による注

IESG では、以下のメカニズムではドットを含まないようなホスト名を扱う時には .local トップレベルドメイン (TLD) を内部的に使用しているが、その拡張的手法は将来登録されるかもしれない実際の .local TLD では作動しないであろう、という事を注記する。

概要

この文書はハイパーテキスト転送プロトコル (HTTP) のリクエストとレスポンスの中で状態を持つセッションを構築する方法を記述する。 そこでは Cookie, Cookie2, Set-Cookie2 という三つの新しいヘッダを示し、セッション中のオリジンサーバとユーザエージェントの間で状態情報を運搬する。 ここで記述される方法は Netscape の Cookie 提案 [Netscape] とは異なっているが、Netscape の方法を使用する HTTP/1.0 ユーザエージェントとは相互操作する事ができる (履歴の章を参照)。

この文書は RFC 2109 の実装による経験を反映し、それを廃案にするものである。

1.専門用語

ユーザエージェント、クライアント、サーバ、プロキシ、オリジンサーバ、http_URL という用語は HTTP/1.1 の仕様書 [RFC2616] におけるものと同じ意味を持つ。 abs_path と absoluteURI という用語は URI 構文仕様書 [RFC2396] におけるものと同じ意味を持つ。

ホスト名 (HN) とは、ホストドメイン名 (HDN) とホストの数的インターネットプロトコル (IP) アドレスのどちらかを意味する。 十分条件ドメイン名{fully qualified domain name} がより好まれ、数的 IP アドレスは推奨されない。

リクエストホストとリクエストURI という用語はそれぞれ、クライアントがサーバに HTTP リクエストラインの absoluteURI (http_URL) のホスト (ポートは含まない) と abs_path の部分として送るであろう部分の値を指す。 リクエストホストは HN である事に注意せよ。

有効ホスト名という用語はホスト名に関係する。 もしホスト名がドットを含んでいなければ、有効ホスト名はそれに .local という文字列を付け加えた名前である。 そうで無ければ、有効ホスト名はホスト名と同じである。 全ての有効ホスト名は少なくとも1つのドットを含んでいる事に注意せよ。

リクエストポートという用語は HTTP リクエストラインの absoluteURI(http_URL) のポートの部分を指す。 absoluteURI が明示的なポートを持たない場合、リクエストポートは HTTP の既定である 80 である。 クッキーのリクエストポートは Set-Cookie2 レスポンスヘッダ中がユーザエージェントへ返されたリクエストのリクエストポートである。

ホスト名は IP アドレスか HDN 文字列のいずれかで特定する事ができる。 時々我々はあるホスト名を他のホスト名と比較する。 (その様な比較は大文字・小文字を区別しないものとする。) 以下の場合ホスト A の名前とホスト B の名前はドメイン一致する。

ドメイン一致は可逆操作では無い事に注意せよ。 すなわち、a.b.c.com は.c.com とドメイン一致するが、逆は成立しない。

ホスト名 H の範囲 R は以下のように定義される。

パスを表す2つの文字列 P1 と P2 について、P2 が P1 の接頭辞である場合 (P1 と P2 の文字列比較が等しい場合を含む) 場合、P1 は P2 にパス一致する。 従って、/tec/waldo という文字列は /tec にパス一致する。

それは Netscape の元々の状態管理の実装にて使われていたので、我々はクッキーという用語をオリジンサーバとユーザエージェントの間で受け渡しされ、ユーザエージェントによって保存される状態情報を指す。

1.1 必要条件

この文書中における "MAY", "MUST", "MUST NOT", "OPTIONAL","RECOMMENDED", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULDNOT" という各キーワードは、RFC 2119 [RFC2119] にて記述されるように解釈される。

2. 状態とセッション

この文書は、HTTP のリクエストとレスポンスの中で状態を持つセッションを構築するための方法を記述する。 現在、HTTP サーバはそれぞれのクライアントのリクエストを、それ以前あるいは以降のリクエストと関連付ける事なく応答している; しかし、状態管理メカニズムによって、状態情報を交換したいクライアントやサーバに、より大きな文脈をHTTP リクエストやレスポンスに持たせる事をできるようにし、これを我々は "セッション" と名付ける。 この文脈は、例えば、ユーザの選択を購入の前に集計できるような "ショッピングカート" や、提供されるものが以前ユーザが以前購読していたものに関係するような週刊誌閲覧システムを構築するために使われるであろう。

クライアントもサーバもクッキーをサポートする事は要求されない。 サーバは、サーバが送ったクッキーを返さないクライアントに内容を提供する事を拒否するかもしれない

3. 定義説明

我々はここにオリジンサーバがユーザエージェントに状態情報を送り、またユーザエージェントがオリジンサーバに状態情報を返すための方法を記述する。 その目的は HTTP とユーザエージェントへの影響を最小限に押さえる事である。

3.1 構文: 一般

Set-Cookie2 と Cookie という、二つの状態管理ヘッダは 属性-値 のペアを含む共通の構文上の特性を持っている。 以下の文法はその表記法、DIGIT (10 進数字) トークンと token (略式に言えば、非特殊、非空白文字のシーケンス)、http_URL をそれらの構文を記述する HTTP/1.1 仕様書 [RFC2616] から使用している。

 av-pairs    =     av-pair *(";" av-pair)
 av-pair     =     attr ["=" value]              ; optional value
 attr        =     token
 value       =     token | quoted-string

属性 (names) (attr) は大文字・小文字を区別しない。 空白は token の間で許されている。 上記の構文記述はオプションとしての値を示している一方で、多くはそれらに attr を必要とする事に注意せよ。

注: 上記構文は、属性と = 記号の間に空白を認めている。

3.2 オリジンサーバの役割

3.2.1 一般

オリジンサーバがセッションの初期化を望む場合、オリジンサーバはセッションを初期化する。 これを行うために、オリジンサーバはクライアントに、Set-Cookie2 という特別なレスポンスヘッダを返す。 (詳細は後述。)

ユーザエージェントがセッションを続ける事を選択する場合、ユーザエージェントはオリジンサーバに Cookie リクエストヘッダ (以下参照) を返す。 オリジンサーバはそれを無視する事もできるし、そのセッションの現在の状態を決定するために使う事もできる。 オリジンサーバはクライアントに同じあるいは異なる情報を持った Set-Cookie2 レスポンスヘッダを送り返す事もできるし、Set-Cookie2 ヘッダを全く送らない事もできる。 オリジンサーバはクライアントに Max-Age=0 を持った Set-Cookie2 ヘッダを送る事によってセッションを有効に終了する。

サーバはどんレスポンスにも Set-Cookie2 レスポンスヘッダを返す事ができる。 ユーザエージェントは Cookie リクエストヘッダを送るべきであり、すべてのリクエストに対して、以下に詳述される別の規則に従うべきである。

オリジンサーバは一つのレスポンスに複数の Set-Cookie2 ヘッダを含む事ができる。 介在するゲートウェイがこのような複数ヘッダを単一のヘッダに折りたたむ事ができるという事に注意せよ。

3.2.2 Set-Cookie2 構文

Set-Cookie2 レスポンスヘッダに対する構文は以下のものである。

   set-cookie      =       "Set-Cookie2:" cookies
   cookies         =       1#cookie
   cookie          =       NAME "=" VALUE *(";" set-cookie-av)
   NAME            =       attr
   VALUE           =       value
   set-cookie-av   =       "Comment" "=" value
                   |       "CommentURL" "=" <"> http_URL <">
                   |       "Discard"
                   |       "Domain" "=" value
                   |       "Max-Age" "=" value
                   |       "Path" "=" value
                   |       "Port" [ "=" <"> portlist <"> ]
                   |       "Secure"
                   |       "Version" "=" 1*DIGIT
   portlist        =       1#portnum
   portnum         =       1*DIGIT

略式に言えば、Set-Cookie2 レスポンスヘッダは Set-Cookie2: トークンの後にコンマで区切られた一つ以上のクッキーのリストを含む。 それぞれのクッキーは NAME=VALUE ペアから始まり、0 個以上のセミコロンで区切られた属性-値 ペアを伴う。 属性-値 ペアについての構文はより以前に示された。 特定の属性とそれらの値の意味を以下に示す。 NAME=VALUE 属性-値ペアはそれぞれのクッキーの最初に来なければならない。 その他の属性がある場合、それはどんな順番でも存在できる。 属性が一つのクッキー中に一つ以上現れる場合、クライアントは最初に現れた属性に関連した値のみを使うものとする。 クライアントは最初以降は無視しなければならない

あるクッキーの NAME はこの仕様書中の属性の一つと同じであるかもしれない。 しかし、クッキーの NAME は Set-Cookie2 の最初に来なければならないので、 NAME とその VALUE は属性-値 ペアを混乱させる事は無い。

NAME=VALUE

必須{REQUIRED}。 状態情報 ("cookie") の名前は NAME であり、その値は VALUE である。 $ から始まる NAME は予約されているので、アプリケーションは使用してはならない

VALUE はユーザエージェントにとって opaque であり、オリジンサーバが送る事を選択したいかなるものでもありえ、ひょっとするとサーバで選択された印字可能な ASCII エンコーディングかもしれない。 ここで "opaque" とは、その内容はオリジンサーバにのみ関心があり、また関連しているという事を暗黙的に意味する。 実際、その内容は Set-Cookie2 ヘッダを調べれば誰でも読む事ができるであろう。

Comment=value

オプション{OPTIONAL}。 クッキーはユーザについてのプライベートな情報を得、それを保存するができるので、Comment 属性の値によってオリジンサーバはそのクッキーをどのように使用するかを記述する事ができる。 ユーザはこのクッキーによるセッションを初期化するか続けるかを決定するためにこの情報を調べる事ができる。 値の文字は UTF-8 エンコーディングでなければならない[RFC2279]

CommentURL="http_URL"

オプション。 クッキーはユーザについてのプライベートな情報を得、それを保存するができるので、CommentURL 属性の値によってオリジンサーバはそのクッキーをどのように使用するかを記述する事ができる。 ユーザはこのクッキーによるセッションを初期化するか続けるかを決定するために URL によって識別される情報を調べる事ができる。

Discard

オプション。 Discard 属性はユーザエージェントが終了した時にそのクッキーを無条件に破棄する様にユーザエージェントに指示する。

Domain=value

オプション。 Domain 属性の値はクッキーが有効であるドメインを指定する。 明示的に指定されたドメインがドットから始まっていない場合は、ユーザエージェントが頭にドットをつける。

Max-Age=value

オプション。 Max-Age 属性の値は delta-seconds であり、クッキーの寿命を秒単位で定義する、10 進数の負で無い整数である。 キャッシュされたクッキーを正しく扱うために、クライアントは HTTP/1.1 仕様書[RFC2616] 中の経過時間の計算規則に従ってクッキーの経過時間を計算すべきである。 経過時間が delta-seconds 秒を越えた時、クライアントはそのクッキーを破棄すべきである。 ゼロ値は、クッキーはすぐに破棄されるべきであるという事を意味する。

Path=value

オプション。 Path 属性の値はこのクッキーを適用するオリジンサーバの URL のサブセットを指定する。

Port[="portlist"]

オプション。 Port 属性はクッキーが Cookie リクエストヘッダによって返されるであろうポートを制限する。 構文では例え portlistの中に一つしか portnum が無くてもオプショナルな portlist のまわりを括る必要がある{REQUIRE} という事に注意せよ。

Secure

オプション。 (値を伴わない) Secure 属性は、そのクッキー中の情報を秘密裏に且つ確実に守るために、ユーザエージェントにこのクッキーを送り返す時はいつでもオリジンサーバに接続する時は (指定されていない)安全な方法のみを用いる様に指示する。

ユーザエージェント (ユーザの制御下に置かれているかもしれない) は、"secure" クッキーに対して妥当と考えられるセキュリティレベルを決定する事ができる。 Secure 属性は、そのクッキーの内容を守る事がセッションの重要性を示しているという、サーバからユーザエージェントへのセキュリティアドバイスとして考えられるべきである。 "secure" クッキーがサーバに送り返された時、ユーザエージェントはサーバからクッキーを受信した時に使用したのと同等である程のセキュリティのレベルを使用すべきである

Version=value

必須。 Version 属性の値は、10 進数整数値で、そのクッキーが対応している状態管理仕様のバージョンを識別する。 この仕様に対しては、Version=1 が適用される。

3.2.3 キャッシュ制御

オリジンサーバは返されるリソースと Set-Cookie2ヘッダの両方のキャッシュの可能性の影響を意識していなければならない。 "共有{public}" 文書のキャッシュは望ましい。 例えば、もしオリジンサーバが Set-Cookie2 レスポンスヘッダが生成されなければならないページに対してセッションの開始を示すための標識として "front door" ページのような共有文書を使用するならば、そのページはオリジンサーバが以降のリクエストを見るために "既に期限切れであるもの{pre-expired}"としてキャッシュに保存されるべきである。 例えばセッションに厳密に非公開な情報を含んでいるような、"非共有{private} 文書" は共有キャッシュにキャッシュされるべきではない

そのクッキーが単一ユーザによる使用を意図する場合、Set-Cookie2 ヘッダはキャッシュされるべきではない。 複数ユーザによって共有される事が意図されている Set-Cookie2 ヘッダはキャッシュする事ができる

オリジンサーバは、状況に応じて以下の追加的 HTTP/1.1 レスポンスヘッダを送るべきである

そして以下の内の一つ

HTTP/1.1 サーバは、レスポンス連鎖中に HTTP/1.0 プロキシが存在しないという事を確実に (バンド外によって) 知っている場合以外は、Set-Cookie2レスポンスヘッダを含んでいるレスポンスにおいて Expires: old-date (ここで old-date とは遠い過去の時刻) を送らなければならない。 HTTP/1.1サーバは、Expires: old-date 指示子に加えて HTTP/1.1 プロキシによるキャッシングを許すために別の Cache-Control 指示子を送る事ができる。 この場合、Cache-Control 指示子は HTTP/1.1 プロキシよって Expires:old-date を上書きするであろう。

3.3 ユーザエージェントの役割

3.3.1 Set-Cookie2 の解釈

ユーザエージェントはそれぞれの (名前か IPアドレスとポートによって区別される) オリジンサーバから Set-Cookie2 レスポンスヘッダ経由で到着する状態情報の分割トラックを維持する。 ユーザエージェントは認識しない属性を持つ 属性-値 ペアは無視しなければならない。 ユーザエージェントは指定が無い時には以下のオプショナルな属性を既定として適用する。

Discard
既定の振る舞いは Max-Age 属性の有無によって指定される。
Domain
有効リクエストホストを既定とする。 (有効リクエストの最初にドットが無いので、既定ドメインは自身にのみドメイン一致するという事に注意せよ。)
Max-Age
既定の振る舞いはユーザエージェントが終了した時にクッキーを破棄するものとする。
Path
Set-Cookie2 レスポンスを生成するリクエスト URL のパスとして、上から最も右の / までを既定とする。
Port
既定の振る舞いではクッキーはどんなリクエストポートにも返す事ができる
Secure
もし存在しなければ、ユーザエージェントは安全でないチャンネルへとクッキーを送る事ができる

3.3.2 クッキーの拒否

起こり得るセキュリティやプライバシーの侵害を防止するために、ユーザエージェントは以下の規則に従ってクッキーを拒否する。 この規則の目標は Path, Domain, Port 属性の値と request-URI,request-host, request-port に基づいて、クッキーが文法上正しいようなサーバのセットに制限を設けようとするものである。

もし Version 属性が無ければ、ユーザエージェントは拒否する (その情報を保存しないものとする)。 そして、もし Set-Cookie2 レスポンスヘッダ中に明示的に存在する属性において以下のうちいずれかが真であれば、ユーザエージェントは拒否する (その情報を保存しないものとする)。

例:

3.3.3 クッキー管理

ユーザエージェントがその NAME が以前に保存していたクッキーのものと同じである Set-Cookie2 レスポンスヘッダを受け取る場合、新しいクッキーは古いものに取って代わる。 この時、Domain 属性の新旧値は大文字・小文字を区別しない文字列比較を用いて同等とする、Path 属性の新旧値は文字列比較的に (大文字・小文字を区別して) 同等とする。 しかし、もし Set-Cookie2 が Max-Age の値にゼロを持っているなら、そのクッキーは (新しい物も古い物も) 破棄される。 そうでなければその Max-Age 有効期限が経過するか、あるいは Discard 属性が与えられていてユーザエージェントがそのセッションを終了するかのどちらかの場合までクッキーは (リソースが許せば) 保持され、その後破棄される。

ユーザエージェントはクッキーを保存しておくための有限の空間を持っているので、例えば、least-recently-used アルゴリズムを使って、それぞれのオリジンサーバが設定するクッキーの最大数の制限に従って、新しいクッキーを保存する空間を作るために古いものを廃棄する事もできる

Set-Cookie2 レスポンスヘッダが Comment 属性を含む場合、ユーザエージェントはそのクッキーに人間が読めるように情報を保存す べきであり、クッキー検査のユーザインターフェースの一部としてコメントテキストを表示すべきである

Set-Cookie2 レスポンスヘッダが CommentURL 属性を含む場合、ユーザエージェントはそのクッキーに人間が読めるように情報を保存すべきであり、クッキー検査のユーザインターフェースの一部としてユーザが好みでhttp_URL リンクを参照できるようにすべきである

クッキー検査のユーザインターフェースでは、ユーザエージェントが Set-Cookie2 レスポンスヘッダを受け取った時に、そのクッキーを受け取るかどうかをユーザが決定できるような能力を含む事ができる。 以下の順序で物事が起こる場合には潜在的な混乱状況が起こるであろう。

ユーザエージェントはこの状況下ではいかなるクッキーも返すべきではない。 ユーザエージェントは、あるユーザエージェントのメカニズムでは受け入れられると考えるであろうが、ユーザは受け入れられないと考えるようなこの状況下で受け取ったいかなるクッキーも破棄する事ができる

ユーザエージェントはユーザにクッキー削除の制御を可能にすべきであるが、そこでは Discard や Max-Age 各属性の制御によってクッキーの有効期間を延ばしてはならない。 たまに使われるクッキーはネットワークアプリケーションに対して "設定ファイル" として機能かもしれないが、ユーザはもしそれが least-recently-used クッキーであったとしてもそれを保存しておこうとする事ができる。 実装しうる一つとしては、チェックボックスを通してクッキーの永続的保存 (あるいは、逆に、即時削除) が可能なインターフェースであろう。

プライバシーについての考察では、ユーザがクッキー管理上で重要な管理手段を持つように指示している。 プライバシーの章ではより多くの情報を含んでいる。

3.3.4 オリジンサーバへのクッキー送信

オリジンサーバにリクエストを送る時、以下に基づいて、リクエストに適用できるクッキーを保持していた場合、ユーザエージェントは Cookie リクエストヘッダを含める。

ヘッダの構文は以下の様になる。

 cookie          =  "Cookie:" cookie-version 1*((";" | ",") cookie-value)
 cookie-value    =  NAME "=" VALUE [";" path] [";" domain] [";" port]
 cookie-version  =  "$Version" "=" value
 NAME            =  attr
 VALUE           =  value
 path            =  "$Path" "=" value
 domain          =  "$Domain" "=" value
 port            =  "$Port" [ "=" <"> value <"> ]

cookie-version 属性値は、Set-Cookie2 レスポンスヘッダの Version 属性に相当する値でなければならない。 そうでない場合、cookie-version の値は 0 である。 path 属性値が与えられた場合は、Set-Cookie2 レスポンスヘッダの Path 属性に相当する値でなければならない。 そうでない場合、その属性は Cookie リクエストヘッダから削除されるべきである。 domain属性値が与えられた場合は、Set-Cookie2 レスポンスヘッダの Domain 属性に相当する値でなければならない。 そうでない場合、その属性は Cookieリクエストヘッダから削除されるべきである

Cookie リクエストヘッダの port 属性が与えられた場合は、Set-Cookie2 レスポンスヘッダの Port 属性に相当する値を写さなければならない。 これは、Port 属性が Set-Cookie2 ヘッダ中に与えられた場合は port 属性も与えられなければならない し、しかもそれがいかなる値であっても、同じ値でなければならない からである。 そうで無い場合、つまり Port 属性が Set-Cookie2 ヘッダ中に無ければ、port 属性も同様に Cookie リクエストヘッダからは削除されなければならない

Cookie リクエストヘッダの Comment や CommentURL 各属性に相当する Set-Cookie2 レスポンスヘッダの属性は存在しない事に注意せよ。 ユーザエージェントはオリジンサーバにコメント情報を返さない。

ユーザエージェントは、自身が保持している全てのクッキーの中から Cookieリクエストヘッダ中で送るために適用できる cookie-value を選択するために以下の規則を適用できる。

Domain 選択

オリジンサーバの有効ホスト名はクッキーの Domain 属性とドメイン一致しなければならない

Port 選択

起こり得る振る舞いは三つあり、これは Set-Cookie2 レスポンスヘッダ中の Port 属性に依存する。

  1. 既定では (Port 属性が無い場合)、そのクッキーはあらゆるポートに送る事ができる
  2. 属性は与えられるが値が無い (例えば、Port) 場合、そのクッキーはそれが受け取られたリクエストポートにのみ送られなければならない
  3. 属性が port-list を持っている場合、そのクッキーは新しいリクエストポートが port-list 中に列挙されている内の一つにのみ返されなければならない
Path 選択

リクエストURI はクッキーの Path 属性とパス一致しなければならない

Max-Age 選択

期限切れになったクッキーは破棄されるべきであるのでオリジンサーバには転送されない。

もし複数のクッキーが上記の基準を満たしていたら、それらはより詳細な Path 属性を持つものがそうで無いものよりも先に来るように Cookie ヘッダの中で順序付けられる。 他の属性 (Domain 等) に関する順序付けは定義しない。

注: 後方互換のために、Cookie ヘッダのセパレータはどこでもセミコロン(;) である。 サーバは将来の互換性のために cookie-value の間のセパレータとしてコンマ (,) も受け入れるべきである

3.3.5 バージョンがいくつであるかを識別: Cookie2

Cookie2 リクエストヘッダは異なるクッキーの仕様のバージョンを理解するためにクライアントとサーバの間で相互に作業する事を容易にする。 クライアントが一つ以上のクッキーをオリジンサーバに送る時、もし少なくともそれらクッキーの内の一つがクライアントが理解するバージョンとは異なる値の $Version 属性を含んでいるならば、クライアントは Cookie2 リクエストヘッダも送らねばならない。 その構文は以下の通りである。

 cookie2 =       "Cookie2:" cookie-version

ここで cookie-version の値はクライアントが理解できる最も高いクッキーの仕様のバージョン (現在は 1) である。 クライアントはリクエストに付きそのようなリクエストヘッダを多くとも一つ送る必要がある。

3.3.6 証明できないトランザクションにおけるクッキー送信

ユーザはプライバシーを保証するためにセッション上で制御を持たなければならない。 (下記プライバシーの章参照。) しかし、実装を単純化するためや、十分な安全保護が存在する複雑なレイヤの追加を防ぐため、この文書は証明できるトランザクションと証明できないトランザクションとを区別する。 もしユーザ、あるいはユーザが指示したエージェントが、トランザクションにおいてそれを使用する前にリクエスト URI を再検討するためのオプションを持っていれば、トランザクションは証明できる。 ユーザがそのオプションを持っていなければトランザクションは証明できない。 典型的に証明できないトランザクションは、ユーザエージェントが自動的にインライン化されたり埋め込まれたりしたエンティティを要求する時、あるいはオリジンサーバからリダイレクション (3xx) されたレスポンスを解決する時に起こる。 典型的に、ユーザが始めた、元々のトランザクションは証明でき、そのトランザクションがユーザエージェントに証明できないトランザクションを作るよう直接もしくは間接的に引き起こすであろう。

そのリクエストホスト U が元々のトランザクション中のリクエストホスト Oの範囲 R とドメイン一致しない場合、証明できないトランザクションは第三のホストに向けてである。

それが証明できないトランザクションをもたらす時、トランザクションが第三のホストに向けてであったら、ユーザエージェントは全てのクッキー処理を中止しなければならない (例えば、クッキーを送信してはならないし、そしていかなるクッキーも受け入れてはならない)。

この制限は、悪意のあるサービス製作者に別のドメインにあるサーバとのセッションをユーザエージェントに開始させたり続行させるような証明できないトランザクションを使わせないようにする。 そのようなセッションの開始や続行はユーザのプライバシーの期待に反し、セキュリティ問題ともなりうる。

ユーザエージェントはユーザエージェントや、ユーザエージェントが実行する自主的なプログラムが、上記の規定を無視できるような、再設定されるまで既定が "off" になっているような、設定可能なオプションを提供する事ができる

(注意 メカニズムは制御状態下で第三の制限を上書きする事を自動化するであろう事を提案されるかもしれない。)

現在のユーザエージェントの多くは、多くのリンクが証明できる事を提示するような再検討オプションを既に供給している。 例えば、あるユーザエージェントではマウスポインタがそのリンク上に置かれた時に詳細なリンクとして参照されている URL を表示する。 それ故に、ユーザはブラウザに表示させる前にそのサイトを訪問するかどうかを決定する事ができる。 (現在使用されているユーザエージェントは実装されていないが、似たような技術はフォームをサブミットするために使用されるボタンに対して使用する事ができる --ユーザエージェントはユーザがこのボタンを選択した場合に行われるアクションを表示できる。 ) しかし、これでさえすべてのリンクを証明するわけではない; 例えば、自動的にロードされる画像へのリンクは通常 "マウスポインタ" 証明を受けない。

また多くのユーザエージェントは、ユーザが文書の HTML ソースを表示したり、別のアプリケーションによって表示するために外部ファイルへソースを保存するためのオプションも供給している。 そのようなオプションが未熟な再検討メカニズムを供給している一方で、ユーザの中にはこの目的のためにそれを受け入れ可能とはみなさないかもしれないものもいる。

3.4 オリジンサーバの Cookie ヘッダの解釈方法

ユーザエージェントはリクエストURI がクッキーの Path 属性にパス一致する時にオリジンサーバに向けて Set-Cookie2 ヘッダ中に多くの情報を返す。 オリジンサーバは Cookie ヘッダを受け取った時、前に $ がつく NAME のクッキーを、そのクッキーのための属性として、特別に扱うべきである

3.5 キャッシングプロクシの役割

状態情報を URL と文書内容の両方から分離する理由の一つは、キャッシングの許可の基準化を容易にするためである。 クッキーをサポートするためには、キャッシングプロクシは HTTP の仕様中の以下の規則に従わなければならない

プロクシはプロクシのレスポンス (リクエスト) においてそれら自身の Set-Cookie2 (Cookie) ヘッダを導入してはならない

4. 例

4.1 例 1

リクエストやレスポンスヘッダの最細部は省略されている。 ユーザエージェントはクッキーを保存していないと仮定する。

  1. ユーザエージェント -> サーバ
     POST /acme/login HTTP/1.1
     [form data]
    

    ユーザはフォームを通して個人を識別する。

  2. サーバ -> ユーザエージェント
     HTTP/1.1 200 OK
     Set-Cookie2: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"
    

    クッキーがユーザの個人情報を反映する。

  3. ユーザエージェント -> サーバ
     POST /acme/pickitem HTTP/1.1
     Cookie: $Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme"
     [form data]
    

    ユーザは "ショッピングバスケット" の品目を選ぶ。

  4. サーバ -> ユーザエージェント
     HTTP/1.1 200 OK
     Set-Cookie2: 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"
     [form data]
    

    ユーザはフォームから発送方法を選ぶ。

  6. サーバ -> ユーザエージェント
     HTTP/1.1 200 OK
     Set-Cookie2: 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"
     [form data]
    

    ユーザは注文の処理を選ぶ。

  8. サーバ -> ユーザエージェント
     HTTP/1.1 200 OK
    

    トランザクションは完了する。

ユーザエージェントは、新しいクッキーのそれぞれを受け取った後に、オリジンサーバ上に一続きのリクエストを作る。 すべてのクッキーは同じ Path 属性と (既定) ドメインを持つ。 リクエストURI はすべて、それぞれのクッキーの Path 属性である /acme とパス一致しているので、それぞれのリクエストはここまでに受信したすべてのクッキーを含んでいる。

4.2 例 2

この例では Path 属性の効果を説明する。 リクエストとレスポンス各ヘッダの詳細部はすべて省略されている。 ユーザエージェントはクッキーを保存していないと仮定する。

ユーザエージェントは、これ以前のリクエストに対するレスポンスで、以下の二つのレスポンスヘッダを受信していると想像せよ。

 Set-Cookie2: Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"

 Set-Cookie2: 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 の接頭辞では無いので、このクッキーはサーバに転送されない。

5. 実装についての考察

ここでは、我々が状態管理を実装するオリジンサーバについて適当な、あるいは望ましい案内を提案する。

5.1 Set-Cookie2 の内容

オリジンサーバの内容は、おそらく状態情報の使用を必要とするような、いくつかのアプリケーション領域から外れた所に分けられるべきである。 アプリケーション領域はそれらのリクエストURL によって区別できる。 Set-Cookie2 ヘッダはそれぞれの領域に対して Path 属性を設定する事でアプリケーション領域についての情報を結びつける事ができる。

セッション情報は状態を表すテキストを明瞭化する、あるいは符号化する。 しかし、もしそれが長くなり過ぎれば、扱いにくくなるだろう。 それ故に、実装者はそのセッション情報がサーバ側のリソースへの鍵となるように選択する事ができる。 もちろん、データベースを使う事はこの状態管理の仕様が避ける事を意図されるようないくつかの問題を発生する。 すなわち:

  1. サーバ側で本当の状態を保持する
  2. ユーザエージェントが、例えば退出による、そのセッションを終わるような場合に、どのように、いつデータベースエントリを回収{garbage-collect} するか

5.2 状態の無いページ

キャッシングは WWW の能力拡大機能{scalability} に利益をもたらす。 その故に、本来的に状態が埋め込まれたような文書の数を減らす事は重要である。 例えば、もしショッピングバスケット形式のアプリケーションがそれぞれのページでユーザの現在のバスケットの内容を常に表示するならば、それぞれのユーザのバスケットの内容は異っているであろうので、それらのページはキャッシュする事はできない。 一方、もしそれぞれのページにユーザが "私のショッピングバスケットを見る" というリンクだけを含んでいれば、そのページはキャッシュできる。

5.3 実装の限界

実際のユーザエージェント実装はそれらが保存できるクッキーのサイズや数に制限を持つ。 一般的に、ユーザエージェントのクッキーサポートは固定した制限を持つべきではない。 それらはできるだけ多くの頻繁に使用されるクッキーを保存するよう努めるべきである。 なお、一般使用のユーザエージェントは個別に以下の最小限の容量を提供すべきであるが、同時にすべてが必要と言うわけではない。

特定の目的あるいは容量が制限されたデバイスのために作られたユーザエージェントは、ユーザがセッションに基づいたオリジンサーバと相互作用する事を保証するために、最低 4096 バイトの 20 のクッキーを提供すべきである

Set-Cookie2 レスポンスヘッダの情報はその完全体を保持されなければならない。 もしある理由によってクッキーを保存するためには不十分な空間しか無いのであれば、それは先頭を切り詰めるのでは無く、破棄されなければならない

アプリケーションはできるだけ少なくまた小さなクッキーを使用すべきであり、クッキーの損失には上手に対処すべきである。

5.3.1 サービス拒否

アタックユーザエージェントは与えられたホストあるいはドメイン名から保存されるクッキーの数やクッキー情報のサイズの上限を設定する事を選択できる。 そうでなければ、悪意のあるサーバは、肯定的レスポンス上で、多数のクッキーや、巨大なクッキーによってユーザエージェントをあふれさせようとする事ができ、それによってユーザエージェントが他のサーバから受け取ったクッキーを強制的に消すだろう。 しかし、それでも上記に指定された最小限度はサポートされるべきである

6. プライバシー

告知の上の同意{informed consent} がクッキーを使うシステムのデザインを導くべきである。 ユーザはどのようにウェブサイトがクッキーの情報を使おうとしているのかを見出せるべきであり、それらの方針が受け入れられるかどうかを選択できるべきである。 ユーザエージェントとオリジンサーバの両方が告知の上の同意を支えなければならない。

6.1ユーザエージェントの制御

オリジンサーバは、サーバを通してユーザの経路を探査するために Set-Cookie2 ヘッダを生成する事ができる。 ユーザは、たとえ自身らの身元が明らかで無かったとしても、情報の侵入的蓄積としてこの振る舞いに反対する事ができる。 (身元は、例えばユーザがその後に身元情報を含むフォームに書き込んだ後に明らかになるであろう。 ) このため、この状態管理仕様ではユーザエージェントはそのような起こり得る侵入に対するユーザの制御機構を与える事を要求するが、ユーザがこの制御を与えるためのインターフェースは記述されないままである。 しかしながら、供給される制御メカニズムによってユーザは少なくとも以下の制御ができる *ものとする*。

そのような制御は、例えば以下のようなメカニズムによって供給され得る。

ユーザエージェントは普通状態情報を記憶しないで実行を開始する。 ユーザエージェントは決して Cookie ヘッダを送信しないように設定する事が可能であるべきである が、この場合オリジンサーバとの状態を維持する事はできないであろう。 (この時ユーザエージェントは Set-Cookie2 レスポンスヘッダを扱う方法を知らないように振る舞うであろう。)

ユーザエージェントが実行を終了した時、ユーザにすべての状態情報を破棄させるべきである。 あるいは、ユーザエージェントは状態情報が維持されるべきかどうかをユーザに尋ねる事もできる が、その既定は "no"となるべきである。 ユーザが状態情報を維持する事を選択した場合は、次回ユーザエージェントが実行する時に回復されるであろう。

注: ユーザエージェントは長い間クッキーを保存するためのファイルを使用する事についておそらく注意深くあるべきである。 もしユーザがユーザエージェントの一つ以上のインスタンスを実行するならば、そのクッキーは混合されるか、さもなくば失敗する。

6.2 オリジンサーバの役割

オリジンサーバは自身が送るクッキーに CommentURL や Comment の情報を加える事によって告知の上の同意を促進すべきである。 情報を提供するための機会が言語の多様さの中でより豊かであるので CommentURL の方がより好まれる。

6.3 クリアテキスト

Set-Cookie2 や Cookie の各ヘッダ中の情報は保護されていない。 その結果として:

  1. それらの中によって伝えられるあらゆる機密性の高い情報は侵入者へさらされる。
  2. 悪意のある仲介者は、それらをどこかに転送させ、予測できない結果を伴うようにヘッダを変える事ができる。

これらの事実は、個人的/金銭的性質の情報は安全なチャンネル上でのみ送信されるべきである事を暗に意味している。 機密性の高い情報をより少なくするため、あるいはそのヘッダの内容がデータベースのキーである時、オリジンサーバは不正な Cookie の値が失敗の原因とならないようにする事を絶えず注意すべきである。

ユーザ環境が共有されるユーザエージェントでは更なる危険が起こる。 クッキー検査のインターフェースを使う事で、ユーザ B はユーザ A がマシンを使った時に保存されたクッキーの内容を調べる事ができる。

7. セキュリティについての考察

7.1 プロトコルデザイン

Domain 属性の値の制限や、証明できないトランザクションに関する規則はクッキーが "悪い" サイトへと "漏れる" ための方法を減らす事を意図している。 その目的はそのサイトや、関係する閉じたホストのセットへのクッキーを制限する事である。 それ故に、リクエストホストは Domain に対して設定できる値と同様に制限される。 我々はホスト host1.foo.com やhost2.foo.com がクッキーを共有する事は受け入れ可能とみなすが、a.com や b.com は受け入れ可能とはみなさない。

同様に、あるサーバはクッキーに対してリクエストURI に関連される Path のみを設定する事ができる。

7.2 クッキースプーフィング

適切なアプリケーションデザインは関連するドメインからの偽造{spoofing} アタックを回避する事ができる。 以下を考える。

  1. ユーザエージェントは victim.cracker.edu へのリクエストを作成、返されたクッキー session_id="1234" を受け取りその既定ドメイン名を victim.cracker.edu に設定する。
  2. ユーザエージェントは spoof.cracker.edu へのリクエストを作成、返されたクッキー session-id="1111" を受け取るが、これはDomain=".cracker.edu" を持つ。
  3. ユーザーエージェントは再び victim.cracker.edu へのリクエストを作成し、以下のクッキーを渡す。
     Cookie: $Version="1"; session_id="1234",
             $Version="1"; session_id="1111"; $Domain=".cracker.edu"
    
    victim.cracker.edu のサーバは、二番目のクッキーはその Domain 属性が自身に対するものでは無いという事に注目する事でそれが自身によって生成されたものではないという事を検出すべきであり、それを無視すべきである。

7.3 予期しないクッキーの共有

ユーザエージェントは、異なるドメインであるホスト間の状態情報の共有を妨げるようなあらゆる試みを作るべきである。 特に、埋め込まれたりインライン化されたオブジェクトはそれらが本質的に異なるホスト間でクッキーを共有するために使用される場合、深刻なプライバシー問題を引き起こしうる。 例えば、悪意のあるサーバはホスト b.com 上の CGI に対する URI 中にホスト a.com に対するクッキー情報を埋め込む事ができる。 ユーザエージェントの実装者には、可能な限りこの種の交換を妨げる事を強く推奨する。

7.4 アカウント情報のためのクッキー

クッキーは、アカウント名やパスワードのような認証情報を保持するためには、クッキーをこのように使う事が共通の習慣である間は、使われるように設計あるいは意図されない。 そのようなクッキーは暗号化された path を通じて交換されるので無ければ、それらが含んだアカウント情報は盗み読まれる可能性が非常に高い。

8. その他の同様な提案

RFC 2109 の他に、三つの他の提案が同様の目的を達成するために作られてきた。 この仕様書は Kristol の State-Info 提案 [DMK95] と Netscape のCookie 提案 [Netscape] の混合物として開始した。

Brain Behlendorf は、ユーザエージェントによって初期化され、またオリジンサーバが "クリック跡" を追跡する事ができるような Session-ID ヘッダを提案した。 しかしながら、これはオリジンサーバが定義したどんな状態も運搬しないであろう。 Phillip Hallam-Baker は同様の目的のために別のクライアント定義セッション ID メカニズムを提案している。

セッション ID とクッキーの両方が状態を持つセッションを維持するための方法を提供する一方で、それらの意図する目的は異なり、そしてその結果、それらに対するプライバシー要求は異なっている。 ユーザは、サーバがそれらを通じて使用して過程の追跡を行う事ができるように、あるいは共有マシーン上で複数のユーザを区別できるように、セッション ID を初期化する。 クッキーはサーバによって初期化されるので、ここで述べられたクッキーメカニズムはユーザが知る事無く別の方法で置き換えるような何かを通じてユーザに制御を与える。 なお、セッション ID がユーザによって選択された簡単な情報から成るのに対して、クッキーはサーバによって選択された豊富な情報を伝える。

9. 履歴

9.1 既存の実装との互換性

既存のクッキー実装は、Netscape の仕様に基づいているが、(Set-Cookie2 では無く) Set-Cookie ヘッダを使用する。 同じクッキーに対して Set-Cookie と Set-Cookie2 の両レスポンスヘッダを同じレスポンス中に受け取るユーザエージェントは Set-Cookie の情報を破棄し、Set-Cookie2 の情報のみを使用しなければならない。 なお、ユーザエージェントは、Set-Cookie2 レスポンスヘッダを受け取った場合、送信したサーバはこの文書に従い、またこの仕様書に従った Cookie リクエストヘッダも理解するであろうという事を仮定しなければならない

新しいクッキーは同等の古い仕様のクッキーと新しい仕様のクッキーを置き換えなければならない。 これは、この仕様にも Netscape の元々の仕様にも従うユーザエージェントが Set-Cookie2 レスポンスヘッダを受け取り、NAME, Domain, Path 各属性が (クッキー管理の章に従って) 一致した場合、Netscape 仕様のクッキーは破棄されなければならない し、ユーザエージェントはこの仕様を守ったクッキーのみを保持しなければならない

この仕様は理解しないが、Netscape の元々の仕様は理解するような古いユーザエージェントは Set-Cookie2 レスポンスヘッダを認識しないであろうし、古い仕様に従ってクッキーを送受信するであろう。

この仕様も Netscape 仕様のクッキーもサポートするユーザエージェントはクッキーを Set-Cookie2 レスポンスヘッダでは無く Set-Cookie レスポンスヘッダで受け取った場合、より古い Netscape 仕様に従う Cookie リクエストヘッダを送るべきである。 しかし、その上でユーザエージェントは以下のリクエストヘッダを送るべきである

 Cookie2: $Version="1"

Cookie2 ヘッダは、サーバにユーザエージェントは新しい仕様のクッキーを理解するという事を通知する。 サーバが新しい仕様のクッキーを理解する場合も同様に、状態を持つセッションを、Set-Cookie よりも Set-Cookie2レスポンスヘッダによって続けるべきである。 新しい仕様のクッキーを理解しないサーバは単に Cookie2 リクエストヘッダを無視するであろう。

9.2 キャッシングと HTTP/1.0

HTTP/1.0 に従っているようないくつかのキャッシュでは、HTTP/1.1 以前にヘッダのキャッシュを抑制するためのメカニズムが無かったので、必然的にSet-Cookie2 ヘッダと Set-Cookie ヘッダをキャッシュするであろう。 このキャッシングはセキュリティ問題を引き起こす可能性がある。 オリジンサーバによって Set-Cookie2 と Set-Cookie 各ヘッダと共に転送された文書はたいていキャッシュ不能であるか、"既に期限切れであるもの" となるであろう。 キャッシュが (Expires: <過去の日付> や Pragma: no-cache(HTTP/1.0) や Cache-control: no-cache (HTTP/1.1) に従って) 文書をキャッシュしないような指示に従う限り、キャッシュできない文書は問題は見せない。 しかし、既に期限切れである文書はキャッシュに保存されるかもしれない。 それらは新しいリクエスト毎に再検証 (条件付き GET) を要求するが、キャッシュ操作機構の中にはそれらのキャッシュについての規則に怠慢であるものもあり、時々それらを最初に検証する事無く期限切れである文書を送付する。 この要因の組み合わせによって、あるユーザに与えるつもりであったクッキーが後になって別のユーザに送られるという可能性がある。 Set-Cookie2 と Set-Cookie 各ヘッダがキャッシュ中に保存されているが、その文書は古く (期限切れと) なっている時、キャッシュは後のリクエストへのレスポンスの中に、文書にキャッシュされたヘッダを含めて返す。

10.謝辞

この文書は IETF の HTTP Working Group や、特に筆者達に加えて Roy Fielding, Yaron Goland, Marc Hedlund, Ted Hardie, Koen Holtman, Shel Kaphan, Rohit Khare, Foteos Macrides, David W. Morris という人々との集団的努力を、本当によく表しているものである。

11 筆者のアドレス

 David M. Kristol
 Bell Laboratories, Lucent Technologies
 600 Mountain Ave.  Room 2A-333
 Murray Hill, NJ  07974

 Phone: (908) 582-2250
 Fax: (908) 582-1239
 EMail: dmk@bell-labs.com


 Lou Montulli
 Epinions.com, Inc.
 2037 Landings Dr.
 Mountain View, CA  94301

 EMail: lou@montulli.org

12 参照文献

DMK95
Kristol, D.M., Proposed HTTP State-Info Mechanism, available at <http://portal.research.bell-labs.com/~dmk/state-info.html>, September, 1995.
Netscape
Persistent Client State -- HTTP Cookies, available at<http://www.netscape.com/newsref/std/cookie_spec.html>,undated.
RFC2109
Kristol, D. and L. Montulli, HTTP State Management Mechanism, RFC 2109, February 1997.
RFC2119
Bradner, S., Key words for use in RFCs to Indicate Requirement Levels, BCP 14, RFC 2119, March 1997.
RFC2279
Yergeau, F., UTF-8, a transformation format of Unicode and ISO-10646, RFC 2279, January 1998.
RFC2396
Berners-Lee, T., Fielding, R. and L. Masinter, Uniform Resource Identifiers (URI): Generic Syntax, RFC 2396, August 1998.
RFC2616
Fielding, R., Gettys, J., Mogul, J., Frystyk, H. and T. Berners-Lee, Hypertext Transfer Protocol -- HTTP/1.1, RFC 2616, June 1999.

13 著作権表示全文

Copyright © The Internet Society (2000). All Rights Reserved.

この文章とその翻訳は、複製し他人に配布する事ができ、またその実装についてのコメント、その他の方法を用いた説明、その補助となるような派生的作業はそれらの中に上の著作権表示とこの段落を含む事によって、その全て又は一部を、いかなる制約も受けずに、作成、複製、発表、及び配布する事ができる。 しかしながら、インターネット標準化プロセスにて定義されている著作権のための手続きに従わなければならないような場合の中でインターネット標準を開発するという目的に必要である、あるいは英語以外の言語に翻訳する必要があるという場合を除いて、この文章自体を、その著作権表示や、インターネット学会あるいは他のインターネット団体への参照を削除するような、いかなる変更もできない。

上で認めた制限された許諾は永続的なものであり、インターネット学会及びその継承者や譲渡者によって取り消される事は無い。

この文書とここに含まれた情報は、"そのまま {AS IS}" である事を基に提供され、インターネット学会、及び IETF は、この中の情報の使用が、商用利用及び特定用途においていかなる権利もいかなる暗黙的保障も侵害していないという保障への制限を含め、明示的に又は暗黙的に、全ての保障を放棄する

謝辞

RFC Editer 機構の資金は、現在インターネット学会から提供されている。


#TOP
Copyright © 1999-2008 橋本英彦 (H-Hash), All Rights Reserved.