$Port

Cookie: ヘッダー (HTTP)

[1] Cookie: ヘッダーは、 利用者エージェントに保存されているクッキーを示します。

[95] クッキー一般に関しては、クッキーの項を参照。

仕様書

構文

[65] Cookie: ヘッダーの値は、 cookie-string です。 RFC 6265

[101] cookie-string は、 1個以上cookie-pair の列です。cookie-pair 間には ;SP の2文字の列が必要です。 RFC 6265

  1. cookie-string
  2. *
    1. ;
    2. SP
    3. cookie-string

[66] RFC 6265 に適合する Set-Cookie: 欄を送信し、 利用者エージェントRFC 6265 に適合する処理を行った場合、 >>65 の構文に適合する Cookie: 欄を受け取るはずです >>64

[67] ここで cookie-pairが送信し、利用者エージェントが蓄積していたものをそれぞれ表しています。 それぞれの名前と値の意味は RFC 6265 では定義しておらず、当該アプリケーションにおける意味に従って処理されるべきものです。 Set-Cookie: 時に指定した属性Cookie: には含まれておらず、どの Path に対して発行したものなのか、などを Cookie: だけから判定することはできません。 >>64

[70] しかし実際には利用者エージェントRFC 6265 に適合するとは限りません。 利用者エージェントRFC 6265 に従って Set-Cookie: 欄を構文解析していると仮定すると、 クッキーの名前や値は token で認められない文字を含むことがあります。 先頭と末尾が空白ではなく、 ;= を含まない任意の1文字以上の文字列が名前となり得ます。また値は先頭と末尾が空白ではなく、 ; を含まない任意の0文字以上の文字列となります。

文脈

[75] 利用者エージェントは、蓄積されているクッキーがあれば Cookie: ヘッダー要求に含めます >>24

[5] 利用者エージェントは、 HTTP/1.1 以下要求で複数の Cookie: ヘッダー生成してはなりません >>24

[71] HTTP では一般に複数の同じ名前のヘッダー, で連結しても等価とされていますが、クッキーの名前や値に , が含まれる可能性があり、これが成立しません。 (RFC 6265 の構文は , を名前や値に認めていないので、適合するが発行したクッキーなら曖昧性はありませんが、 そうでないものを側で処理する可能性を想定するのであれば、 , で結合・分割できません。)

[103] HTTP/2 では、1つ以上cookie-pair が値となる Cookie: ヘッダー複数個に分割して含めても構いません >>100

[104] これは、個々の cookie-pair が更新されることを想定したヘッダー圧縮の効率の向上のための策です >>100

[76] しかし利用者エージェントCookie: ヘッダーを省略しても構いません >>24

[77] 例えば「第三者要求クッキーを送信しなくても構いません >>24

[94] 利用者エージェントは、クッキーが無効に設定されている時、 Cookie: ヘッダー要求に含めてはなりません >>93

[99] WebSocket handshake でも使うことができます。


[110] cookie-string は、 curl--cookie でも使われます。

ヘッダーの生成

[78] 利用者エージェントは、次の条件をすべて満たすクッキーを使って Cookie: ヘッダー生成しなければなりません >>24

[11] リダイレクトによって再度 HTTP 要求を送信する場合であっても、 (新しい URL に関して) 通常通り適用される Cookie を調べて Cookie: 頭欄を構築するべきです。

[74] 利用者エージェントは、 Cookie: ヘッダー生成する際にクッキーを次のように整列するべきです >>24

  1. [84] クッキーパスが長いものを短いものより先に
  2. [85] クッキーパスの長さが同じものは、生成時刻が古いものを新しいものより前に

[86] この順序は RFC 6265 の出版時点で一般的な習慣となっているものの、 すべての利用者エージェントがそうしているわけではないとされています >>24。 そのために必須ではなく推奨に留まっているようです。 しかし (誤って) この順序に依存しているも歴史的には存在していることが知られています >>24 から、本来は必須であるべきところのように思えます。
[98] >>84 の条件より、より深いディレクトリー向けのクッキーが先に来ますから、 としてはより前にあるクッキーを使うのがより良い方針のように思われます。 一方 >>85 の方針より、既存のクッキーを上書きするべきクッキーがなぜか上書きされなかった場合により後のクッキーを取るのがより良い方針とも思えます。 名前とパスが同じ重複したクッキーが保存される場合というのはドメインが異なるクッキーが存在する場合です (Set-Cookie: 参照)。

[87] 利用者エージェントは、>>78 で得られたクッキー>>74整列し、 ;SPACE の列で区切って連結したものを Cookie: ヘッダーとして使わなければなりません。ただし、 各クッキーは名前と値を = で連結したものとしなければなりません>>24

[90] 蓄積されていたクッキーRFC 6265 の構文に適合しない名前や値が含まれていた場合には、 ここでそのまま出力することになりますから、 RFC 6265Cookie: ヘッダーの構文に適合しない結果になることもあります。
[91] クッキーの名前や値はバイト列で、ここで連結して得られる結果もバイト列です。
[89] 該当するクッキーが一つもない場合には、 Cookie: ヘッダー自体を生成しません。

[88] また利用者エージェント>>78 で得られたクッキーの最終アクセス時刻を現在日時に設定しなければなりません >>24

処理

[63] 起源鯖Cookie: 欄やその中身を無視して構いません。 >>61

[68] クッキーは順番に並べることになってはいますが、ではそれに依存するべきではありません。 特に、同じ名前のクッキーが複数ある場合に、これがどの順番で現れるかに依存するべきではありません>>64

[73] RFC 6265 は (利用者エージェントによる Set-Cookie: ヘッダーの構文解析を詳細に規定しているのに対して) 起源鯖による Cookie: ヘッダーの構文解析の方法を詳細には規定していません。 が適合する Set-Cookie: ヘッダーを出力し、 利用者エージェントが適合する方法で処理する限り、 Cookie: ヘッダーの値は常に ABNF 構文に適合するはずなので、それ以上に構文解析法を規定する必要もないのかもしれません。 あるいはが内部でどのようにヘッダーの値を解釈するかは側の著者 (開発者) 以外には観測できず、適合性を議論するのが難しいという事情もあるかもしれません。
[92] 起源鯖は、クライアントが仕様に適合しない Cookie: ヘッダーを送信してきた場合にも (エラーを返すなど) 適当な処理を行えなければなりません。 Webブラウザー以外から適合しない Cookie: ヘッダーが送られたり、 Webブラウザーからも (著者のミスや悪意ある利用者により) 適合しない Cookie: ヘッダーが送られたりする可能性は排除できません。 またライブラリーの類は、Webアプリケーションの開発者が不適合な Set-Cookie: ヘッダーを送信している可能性を排除できませんから、 不適合な Cookie: ヘッダーであってもできるだけ“正しく” 処理できることが求められます。

[102] HTTP/1.1 以下Cookie: ヘッダーが複数ある場合にどう処理するべきかは不明です。

[72] RFC 6165がこの辺りをどう処理するべきか特に規定していません。 通常はが名前や値を制御できるので、そのようなものを出力しなければ良いだけです。 ただ実際には他のから第三者的に発行することもできてしまいますし、 側の実装と JavaScript の実装を別の著者が行なってい (て HTTP の制限を見落としてい) る場合など、まったく無視できる問題でもありません。 >>73 の制限があるので、これに従う (一般的な) 利用者エージェントを想定するなら、 ,ヘッダーの連結ではなく、名前や値の一部と常に仮定していいかもしれません。

[105] HTTP/2 で複数の Cookie: ヘッダーがある場合、 HTTP/1.1 接続や汎用 HTTP サーバー応用など HTTP/2 以外へと引き渡される時は、 ;SP の列によって連結して1つにしなければなりません >>100

[62] Cookie: 欄の有無はキャッシュ可能性に影響しません >>61

[10] Cookie: をそのままへと転送するべきです。 それがたとえ If-Modified-Since: つきの条件付き要求であってもです。 >>2

歴史

RFC の Cookie: 頭欄の定義

[19] RFC 2109, RFC 2965 では Netscape Cookie とはあまり互換性がない Cookie: 頭欄が定義されていました >>17, >>18

概要:

[46] Netscape Cookie の互換性について、次のようなことが言われていました >>45

  • [47] 旧クライアントは新しい Cookie を受け取ると知らないものは無視し、理解できるものを使って Cookie: を送る
  • [48] 新クライアントは Cookie を常に新形式で送る
  • [49] 旧鯖は「$]」で始まる属性をそういう Cookie だと思って無視する
    • [50] ただし「,」区切りではなく「;」区切りだと思っている
  • [51] 新鯖は「$Version」の有無で新旧クライアントを区別できる

[52] >>46 を読むと一見後方互換性が保たれていると錯覚してしまいがちですが、 新 Cookie では属性の値が引用文字列でもあり得るので、 旧クライアント・旧鯖は引用符も値の一部だと思ってしまうという問題があります。

  • [54] 起源鯖はクライアントが新 Cookie を理解すると分かっていないときは、引用符が必要な値に注意するべきです。 >>53
  • [55] 新しいクライアントは Cookie の版がすべて RFC 2109 以降であるときだけ値を引用符で括るべきです。 >>53

[56] >>48 より新クライアントは常に新 Cookie を送ることになっているので、 常に引用文字列で送る新クライアントは旧鯖とは正しくやり取りできなくなり、 >>55 のような注意が必要になるわけです。でも >>54 のように注意しろと言われても困った話です。 引用符が必要な値だけど引用符を使えないときは引用符を外していいのでしょうか。 でも外すと RFC 2109 には適合しなくなります。

[57] また、 RFC 2109 は「=」の周りの空白についても、 Netscape Cookie では認められていなかったので注意するよう書いています >>53

[16] RFC 2109RFC 2965 は、利用者エージェントは各種規則に基づき Cookie: 応答頭欄を送信するべきである、としていました。 >>14, >>15
  • [12] RFC 2109 (廃止済み)
    • [14] 4.2.1 General
    • [17] 4.3.4 Sending Cookies to the Origin Server
    • [36] 4.4 How an Origin Server Interprets the Cookie Header
    • [42] 4.5 Caching Proxy Role
    • [45] 10.1.1 Extended Cookie Header
    • [53] 10.1.3 Punctuation
  • [13] RFC 2965
    • [15] 3.2.1 General
    • [18] 3.3.4 Sending Cookies to the Origin Server
    • [37] 3.4 How an Origin Server Interprets the Cookie Header
    • [43] 3.5 Caching Proxy Role

実装

[58] Mojo::Cookie::Request - search.cpan.org ( 版) http://search.cpan.org/~kraih/Mojolicious-0.999926/lib/Mojo/Cookie/Request.pm

Netscape Cookie に加え、 RFC 2109RFC 2965Cookie: の構文解析に対応しています。

CGI メタ変数

[59] CGIメタ変数 HTTP_COOKIEHTTPCookie: 欄に対応します。詳しくは HTTP_* を参照してください。

[60] WebSiteHTTP_COOKIE のかわりにメタ変数 COOKIE を使っているそうです。

関連

[6] Cookie を設定する Set-Cookie: 頭欄と同じように名前と値の組を並べる形式ではありますが、 Set-Cookie: は1つの名前と値の組を設定するのに対し、 Cookie: は複数の名前と値の組を1つにまとめて記述できます。

[96] draft-pettersen-cookie-origin-02 - Identifying origin server of HTTP Cookies ( ( 版)) http://tools.ietf.org/html/draft-pettersen-cookie-origin-02

[97] draft-willis-sip-cookies-00 - SIP Cookies ( ( 版)) https://tools.ietf.org/html/draft-willis-sip-cookies-00#section-4

[106] Clarify the hooks into RFC6265 · whatwg/fetch@5a324a8 ( 版) https://github.com/whatwg/fetch/commit/5a324a891c42d42de09a01e03c3a063b9a4f882b

[107] CVE-2016-7401 CSRF protection bypass on a site with Google Analytics の解説 · GitHub ( ()) https://gist.github.com/mala/457a25650950d4daf4144f98159802cc

多くのcookie parserは、pairsの区切りとして ; と , を許容しているのでdjango以外にも影響がある。 ブラウザが使用するcookie pairの区切りは実際には ;

CGI::Cookieでは "[;,] ?"

[108] , を区切りとする元凶は RFC 2965 とのこと...

[109] Configuration • Akka HTTP () https://doc.akka.io/docs/akka-http/current/configuration.html

# Sets the parsing mode for parsing cookies.

# The following value are defined:

#

# `rfc6265`: Only RFC6265-compliant cookies are parsed. Surrounding double-quotes are accepted and

# automatically removed. Non-compliant cookies are silently discarded.

# `raw`: Raw parsing allows any non-control character but ';' to appear in a cookie value. There's no further

# post-processing applied, so that the resulting value string may contain any number of whitespace, unicode,

# double quotes, or '=' characters at any position.

# The rules for parsing the cookie name are the same ones from RFC 6265.

#

cookie-parsing-mode = rfc6265