RFC 6265 HTTP cookie

HTTP cookie (クッキー) は,ほとんどのWebサーバーとWebブラウザーで利用可能な機能だ。状態を持たないHTTPに対して,状態管理機構を提供する。

クッキーと呼ばれる名前と値の組を,サーバーがHTTP内のSet-CookieヘッダーでUAに送信し,UAはその後の要求でHTTP内のCookieヘッダーにこれらのクッキーを含む。これにより,ログインなどの状態の情報をクッキーに保持することで,状態管理が可能となる。

1997年のRFC 2109で初めて標準化され,2000年のRFC 2965,2011年のRFC 6265で更新された。最新版はRFC 6265であり,日本語訳も存在する。

これらの標準仕様を読み,HTTP cookieについて勉強したので,その内容を整理する。

概観

HTTP cookieは状態情報をHTTP UA (User Agent, ブラウザーなど) に格納させるために,HTTPサーバーに利用される機能だ。これにより,状態を持たないHTTPプロトコル越しに,サーバーがセッションを保守できるようになる。

具体的には,HTTPのCookieヘッダーとSet-Cookieヘッダーを定義する。HTTPサーバーはSet-Cookieヘッダーを利用して,クッ
キーと呼ばれる (名前, 値) の組とそれに紐づくメタデータ (有効期限などの属性)
をUAに渡せる。UAは,サーバーへ後続の要求の発行時に,このメタデータと他の情報を利用して, (名前, 値)
の組をCookieヘッダー内に含めるかどうかを決める。

HTTP cookieの生成元サーバーは,UAに状態を格納させるために,HTTP応答にSet-Cookieヘッダーを含む。UAによる後続の要求では,UAは以前にSet-Cookieヘッダーで受信したクッキーを含んだCookie要求ヘッダーを,生成元サーバーに返信する。

例えば,サーバーはUAへのHTTP応答に,Set-Cookieヘッダー利用して,短い文字列を送信できる。送信された文字列は,その後のUAのHTTP要求に含まれる。これにより,セッションIDを後続のUAからの要求を維持できる。

== Server -> UA ==
Set-Cookie: SID=31d4d96e407aad42

== UA -> Server ==
Cookie: SID=31d4d96e407aad42

その他,サーバーはPath属性と Domain属性を利用して,クッキーの可視性を指定できる。例えば,example.comのどのパス,あるいはどの下位ドメインに対しても,そのクッキーを応答するように指令できる。

== Server -> UA ==
Set-Cookie: SID=31d4d96e407aad42; Path=/; Domain=example.com

== UA -> Server ==
Cookie: SID=31d4d96e407aad42

複数のクッキーをUAに格納できる。機密性の高い情報は,SecureやHttpOnly属性を使用できる。

また,UAを複数のセッション (UAの再起動) に渡ってクッキーを維持したい場合,サーバーはExpires属性に,有効期限を指定できる。クッキーの保管容量超過時や手動で削除した場合など,有効期限前にUAのクッキーが削除されることがあり得ることに注意する。

== Server -> User Agent ==

Set-Cookie: lang=en-US; Expires=Wed, 09 Jun 2021 10:18:14 GMT == User Agent -> Server == Cookie: SID=31d4d96e407aad42; lang=en-US

複数のSet-Cookieヘッダーにより,複数のクッキーを渡せる。

== Server -> User Agent ==

Set-Cookie: SID=31d4d96e407aad42; Path=/; Secure; HttpOnly
Set-Cookie: lang=en-US; Path=/; Domain=example.com

== User Agent -> Server ==

Cookie: SID=31d4d96e407aad42; lang=en-US

属性

Set-Cookieヘッダーに指定可能な属性を以下に示す。

HTTPクッキーの属性
属性 既定 説明
Expires 現在のセッション終了時 クッキーの最長の存続期間を指定する。クッキーの失効日時で表現する。あくまで最長の存続期間であり,この期限内でもUAによる削除がありえる。過去の日時の指定でクッキーを削除できる。
Max-Age 現在のセッション終了時 クッキーの最長の存続期間を指定する。クッキーの失効までの秒数で表現する。一部の既存のUAはMax-Ageに対応しない。Max-AgeとExpiresの両方が存在する場合,Max-Ageが優先される。どちらも存在しない場合,UAが定義する「現在のセッションの終了」までクッキーを維持する。ブラウザーであれば,ブラウザー終了まで維持される。
Domain クッキー生成元サーバー クッキーの送信対象ホストを指定する。サブドメインも含む。例えば,Domain属性がexample.comの場合,example.com, www.example.com, www.corp.example.comなどへのHTTP要求時にクッキーを含む。先頭の%x2E (“.”) は無視されるが,末尾に%x2E (“.”) が存在する場合,UAはこの属性を無視する。省略した場合,クッキーの生成元サーバーにのみクッキーを返す。
一部のUAは,Domain属性の指定がなくても,現在のホスト名が指定されたかのように振る舞い,サブドメインにもクッキーを返してしまう。
セキュリティの観点から,多くのUAはトップレベルドメインの指定のDomain属性のクッキーを拒絶する。
Path 要求URIのパス クッキーの可視性を指定したパスの集合に限定する。要求URIのパス部位がPath属性に一致するまたはその下位ディレクトリーである場合にのみ,クッキーを含む。%x2F (“/”) は,ディレクトリの区切りとして解釈される。
Secure クッキーの可視性をセキュアチャンネルに限定する。セキュアの意味はUAにより定義される。ブラウザーの場合,HTTPS通信 (TLS) と思われる。セキュア通信時にのみ該当クッキーを含む。機密性のみを保護するので,外部からの上書きがありえる。
HttpOnly クッキーの可視性をHTTP通信に限定する。

HTTPクッキーの属性一覧を眺めて,使う属性と,使わない属性を以下のように判断した。

指定推奨属性
  • Expires: クッキー削除時と,ブラウザー終了後も維持したい場合に指定。
  • Path: クッキーの使用可能範囲を広げるため,”/” を基本的に指定。
  • Secure: IDやパスワードなどの機密性保持のため,基本的に指定。
指定非推奨属性
  • Max-Age: 対応しないUAが存在し,Expiresで対応できるので使わない。
  • Domain: 基本的にドメインをまたぐ必要はないので,指定しない。
  • HttpOnly: クッキーの使用可能範囲が狭まるので,基本的に使わない。

基本動作

保存

クッキー名,Domain属性,Path属性の全てが同じ場合,クッキーが更新される。それ以外の場合,該当する条件で新しいクッキーが保存される。

また,UAが認識できない属性が存在する場合,UAはその属性のみを無視する。

11. If the cookie store contains a cookie with the same name,
domain, and path as the newly created cookie:

1. Let old-cookie be the existing cookie with the same name,
domain, and path as the newly created cookie. (Notice that
this algorithm maintains the invariant that there is at most
one such cookie.)

2. If the newly created cookie was received from a “non-HTTP”
API and the old-cookie’s http-only-flag is set, abort these
steps and ignore the newly created cookie entirely.

3. Update the creation-time of the newly created cookie to
match the creation-time of the old-cookie.

4. Remove the old-cookie from the cookie store.

5.3. Storage Model | RFC 6265 – HTTP State Management Mechanism

When the user agent receives a Set-Cookie header, the user agent
stores the cookie together with its attributes. Subsequently, when
the user agent makes an HTTP request, the user agent includes the
applicable, non-expired cookies in the Cookie header.

If the user agent receives a new cookie with the same cookie-name,
domain-value, and path-value as a cookie that it has already stored,
the existing cookie is evicted and replaced with the new cookie.
Notice that servers can delete cookies by sending the user agent a
new cookie with an Expires attribute with a value in the past.

4.1.2. Semantics (Non-Normative) | RFC 6265 – HTTP State Management Mechanism
削除

クッキーを削除する場合,有効期限を過去にしたSet-Cookieヘッダーを返す。この除去が成功するのは,Set-Cookie-ヘッダーの中のPathとDomainの両属性とも,クッキー作成時の値に合致する場合に限られる。

RFCを読む限り,クッキーの削除方法はこれしかない。現在日時を指定した場合,即座に有効期限が超過して失効するものの,一瞬UAに保存される。

Finally, to remove a cookie, the server returns a Set-Cookie header
with an expiration date in the past. The server will be successful
in removing the cookie only if the Path and the Domain attribute in
the Set-Cookie header match the values used when the cookie was
created.

3.1. Examples | RFC 6265 – HTTP State Management Mechanism

Notice that servers can delete cookies by sending the user agent a
new cookie with an Expires attribute with a value in the past.

4.1.2. Semantics (Non-Normative) | RFC 6265 – HTTP State Management Mechanism
自動削除

クッキーの有効期限が過去の場合,そのクッキーは失効 (expired) とみなされる。失効したクッキーは全て削除される。

クッキーの削除は以下の優先順位で行われる。

  1. 失効クッキー
  2. 保持限界超過分クッキー
  3. 最古最終アクセスクッキー

現在のセッション終了時に,ExpiresやMax-Ageの指定されていないクッキーは全て削除される。

A cookie is “expired” if the cookie has an expiry date in the past.

The user agent MUST evict all expired cookies from the cookie store
if, at any time, an expired cookie exists in the cookie store.

At any time, the user agent MAY “remove excess cookies” from the
cookie store if the number of cookies sharing a domain field exceeds
some implementation-defined upper bound (such as 50 cookies).

At any time, the user agent MAY “remove excess cookies” from the
cookie store if the cookie store exceeds some predetermined upper
bound (such as 3000 cookies).

When the user agent removes excess cookies from the cookie store, the
user agent MUST evict cookies in the following priority order:

1. Expired cookies.

2. Cookies that share a domain field with more than a predetermined
number of other cookies.

3. All cookies.

If two cookies have the same removal priority, the user agent MUST
evict the cookie with the earliest last-access date first.

When “the current session is over” (as defined by the user agent),
the user agent MUST remove from the cookie store all cookies with the
persistent-flag set to false.

5.3. Storage Model | RFC 6265 – HTTP State Management Mechanism

条件

Set-CookieヘッダーとCookieヘッダー

1個のSet-Cookieヘッダーにつき,1個のクッキーを指定する。値の区切りとしての%x2C (“,”) がクッキー値と衝突するため,1個のSet-Cookieヘッダーに複数のクッキーを指定してはいけない。

Origin servers SHOULD NOT fold multiple Set-Cookie header fields into
a single header field. The usual mechanism for folding HTTP headers
fields (i.e., as defined in [RFC2616]) might change the semantics of
the Set-Cookie header field because the %x2C (“,”) character is used
by Set-Cookie in a way that conflicts with such folding.

3. Overview | RFC 6265 – HTTP State Management Mechanism

UAからの応答のCookieヘッダーは一度に複数のクッキーを含められる。

== Server -> User Agent ==

Set-Cookie: SID=31d4d96e407aad42; Path=/; Secure; HttpOnly
Set-Cookie: lang=en-US; Path=/; Domain=example.com

== User Agent -> Server ==

Cookie: SID=31d4d96e407aad42; lang=en-US

一度のSet-Cookieで同じクッキー名を複数送信する場合,PathやDomain属性をチェックして,同一の場合,後のクッキーで上書きする。そうでなければ,新規に保存する。

ヘッダーのクッキーや属性の間はセミコロン (“;”) で区切る。

Cookieヘッダーで応答されるクッキーには属性は付与されていない。また,クッキーのペアの順番は不定となる。

Although cookies are serialized linearly in the Cookie header,
servers SHOULD NOT rely upon the serialization order. In particular,
if the Cookie header contains two cookies with the same name (e.g.,
that were set with different Path or Domain attributes), servers
SHOULD NOT rely upon the order in which these cookies appear in the
header.

RFC 6265 – HTTP State Management Mechanism
名と値

クッキーの名と値にはUS-ASCII文字しか使えない。

  • クッキー名: 1文字以上の区切り文字 (()<>@,;:\"/[]?={}空白水平タブ) 以外のUS-ASCII文字 (0-127)。
  • クッキー値: CTL (コントロールシーケンス: US-ASCII0-31, DEL (127)), 空白, 二重引用符, カンマ, セミコロン, バックスラッシュ を除くUS-ASCII 文字。二重引用符で囲んでもいい。

set-cookie-header = “Set-Cookie:” SP set-cookie-string
set-cookie-string = cookie-pair *( “;” SP cookie-av )
cookie-pair = cookie-name “=” cookie-value
cookie-name = token
cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
; US-ASCII characters excluding CTLs,
; whitespace DQUOTE, comma, semicolon,
; and backslash
token = <token, defined in [RFC2616], Section 2.2>

4.1.1 Syntax | RFC 6265 – HTTP State Management Mechanism

token = 1*<any CHAR except CTLs or separators>
separators = “(” | “)” | “<” | “>” | “@”
| “,” | “;” | “:” | “\” | <“>
| “/” | “[” | “]” | “?” | “=”
| “{” | “}” | SP | HT

2.2 Basic Rules | RFC 2616 – Hypertext Transfer Protocol — HTTP/1.1

定義にある通り,クッキーの名と値の両方で,日本語などのマルチバイト文字が使えないことに注意する。名と値の両方で%が許可されているので,マルチバイト文字は%エンコードして指定する。

また,名と値の上限値は定義されておらず,UAに依存する。ただし,保存容量の下限の推奨値があるので,これがクッキー設定時の長さの目安となる。

1クッキー当たり最低4096バイトの保存が推奨されているので,クッキー名と値の合計で最低4096文字は利用可能と考えてよいだろう。

容量

UAごとに制限は異なるが,以下の容量の保存を保証すべきだ。

  • 1クッキーあたり,最低4096バイト
  • 1ドメインあたり,最低50個のクッキー
  • 全体で最低3000個のクッキー
  • クッキーの保存容量: 4096 Byte × 3000 = 12288000 Byte = 12000 KB = 11.71675 MB ≒ 12 MB

RFC上すべき (SHOULD) となっているので,保証はないものの,概ねこの保存容量の条件は守られるだろう。

結論

RFC 6265 HTTP cookieの仕様を整理した。

HTTPヘッダーの書式,属性,基本動作,条件などを整理し,HTTP cookieに対しての理解が深まった。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です