Cookieで使用できる文字は何ですか?


301

Cookie名と値の両方で使用できる文字は何ですか?それらはURLまたはいくつかの一般的なサブセットと同じですか?

私が尋ねている理由-は、名前にCookieが含まれる奇妙な動作に最近遭遇したことであり、それがブラウザ固有のものか、コードに欠陥があるのか​​と思っています。

回答:


391

これは簡単です:

あるべきだと思うかもしれませんが、実際にはそうではありません。

Cookie名と値の両方で使用できる文字は何ですか?

古代のNetscape cookie_specによると、NAME=VALUE文字列全体は次のとおりです。

セミコロン、カンマ、空白を除く一連の文字。

だから、-動作するはずです、そして私がここに持っているブラウザでOKであるように見えるん。どこで問題がありますか?

上記の含意:

  • =含めることは合法ですが、あいまいになる可能性があります。ブラウザは常に名前と値を=文字列の最初のシンボルで分割するため、実際に=はNAMEではなくVALUEにシンボルを配置できます。

ネットスケープは仕様を書くのはひどかったが、ブラウザによって一貫してサポートされているように見えるので、言及されていないもの:

  • NAMEまたはVALUEは空の文字列である可能性があります

  • =文字列にシンボルがない場合、ブラウザはそれを空の文字列名を持つcookieとして扱います。つまりSet-Cookie: foo、と同じSet-Cookie: =fooです。

  • ブラウザーが空の名前のCookieを出力する場合、等号は省略されます。だから、Set-Cookie: =bar生まれるCookie: bar

  • 名前と値のコンマとスペースは実際には機能しているように見えますが、等号の前後のスペースは削除されています

  • 制御文字(\x00から\x1Fプラス\x7F)は許可されていません

言及されておらず、ブラウザが完全に一貫していないのは、非ASCII(Unicode)文字です。

  • OperaとGoogle Chromeでは、それらはUTF-8でCookieヘッダーにエンコードされます。
  • IEでは、マシンのデフォルトのコードページが使用されます(ロケール固有で、UTF-8は使用されません)。
  • Firefox(およびその他のMozillaベースのブラウザ)は、各UTF-16コードポイントの下位バイトを独自に使用します(ISO-8859-1は問題ありませんが、その他はすべて破損しています)。
  • Safariは、ASCII以外の文字を含むCookieの送信を拒否します。

したがって、実際にはCookieで非ASCII文字を使用することはできません。Unicode、制御コード、またはその他の任意のバイトシーケンスを使用する場合、cookie_specでは、独自に選択したアドホックエンコーディングスキームを使用し、URLエンコーディング(JavaScriptで生成されたものencodeURIComponent)を合理的な選択肢として提案する必要があります。

実際の標準に関しては、Cookieの動作をコード化する試みがいくつかありますが、これまで実際に現実の世界を反映しているものはありません。

  • RFC 2109は、元のNetscape cookie_specを体系化して修正する試みでした。この標準では、RFC 2616トークンを使用するため(a -引き続き許可されます)、さらに多くの特殊文字が許可されていません。引用符付き文字列には、他の文字を使用して値のみを指定できます。ブラウザーは、制限、引用された文字列とエスケープの特別な処理、またはこの仕様の新機能を実装していません。

  • RFC 2965は別の試みであり、2109を整え、「バージョン2 Cookie」スキームの下でより多くの機能を追加しました。そのいずれも実装したことはありません。この仕様には、以前のバージョンと同じトークンと引用符で囲まれた文字列の制限があり、それはまったく意味のない負荷です。

  • RFC 6265は、歴史的な混乱を一掃するHTML5時代の試みです。それでも現実と正確には一致しませんが、以前の試みよりもはるかに優れています。これは、ブラウザがサポートするものの少なくとも適切なサブセットであり、機能すると想定されているが機能しない構文を導入していません(前の引用文字列のように) 。

6265でも、Cookie名はRFC 2616として指定されていますtoken。つまり、alphanums plusから選択できます。

!#$%&'*+-.^_`|~

Cookie値では、(ブラウザでフィルタリングされた)制御文字と(一貫して実装されていない)非ASCII文字を正式に禁止します。これは、スペース、コンマ、セミコロンに対するcookie_specの禁止事項を保持しています。さらに、以前のRFCを実際に実装した貧弱な馬鹿との互換性のために、値全体を囲む引用符以外のバックスラッシュと引用符も禁止しました(ただし、その場合、引用符はまだ一部と見なされます)コード化スキームではなく値)。それで、英数字プラスが残ります:

!#$%&'()*+-./:<=>?@[]^_`{|}~

現実の世界では、元々最悪のNetscape cookie_specをまだ使用しているため、Cookieを使用するコードは、ほとんどの場合に遭遇するように準備する必要がありますが、Cookieを生成するコードについては、RFC 6265のサブセットを使用することをお勧めします。


@bobince ;二重引用符で囲まれている限り、Cookieの値に文字を含めることができるとRFCが述べていることを意味しますか?そのため:Set-Cookie: Name=Va";"lue; Max-Age=3600
Pacerier

@Pacerier:値全体は引用文字列でなければならないので、でなければなりませんName="Va;lue"; max-age...。これはブラウザーでは機能せず、RFC 6265では許可されていません。RFC6265は、2965を置き換えることが提案され、現実を少しよく反映しようとしています。
ボビンス2012

@bobince-私はこれが古いことを知っていますが、Cookieの値にスペースが技術的に許可されていないことを意味するためにあなたの答えを正しく読んでいますか?「セミコロン、カンマ、ホワイトスペースを除く」 [強調は私のもの]
アダムラッキス

1
@Adam:はい、Netscape仕様またはRFC 6265を使用している場合、未加工の(DQUOTEdでない)Cookie値に空白は許可されません。それでも私が試したブラウザでは機能しますが、私はそれに依存しません。
ボビンス2013

2
RFC 6265のとしてトークン定義1*<any CHAR except CTLs or separators>とセパレータている()<>@,;:\"/[]?={}SPHT、クッキーの名前はalphanumsプラスでなければなりませんので!#$%&'*+-.?^_`|~
ガン泉

28

ASP.Net System.Web.HttpUtilityでは、Cookieに書き込む前にCookie値を安全にエンコードし、それを読み取るときに元の形式に変換するために使用できます。

// Encode
HttpUtility.UrlEncode(cookieData);

// Decode
HttpUtility.UrlDecode(encodedCookieData);

これはアンパサンドと等号を停止し、値がCookieに書き込まれるときに、値を一連の名前/値ペアに分割します。


1
ただ1つの注意点として、内部的にasp.netは、認証Cookieを格納するときにUrlEncodeではなく16進エンコーディングを使用します。referencesource.microsoft.com#System.Web / Security /…したがって、URLエンコードがそれをカットできない場合があるかもしれませんか?
Peter

17

一般的にはブラウザ固有のものだと思います。安全のために、base64はJSONオブジェクトをエンコードし、その中にすべてを格納します。そうすれば、それをデコードしてJSONを解析するだけです。base64で使用されているすべての文字は、すべてのブラウザとは限りませんが、ほとんどのブラウザで正常に再生されます。


この回答は、ブラウザ間で一貫しているようです。何時間も働いて簡単な解決策を模索した結果、これに気付きました。面倒を省くために、上記の推奨事項を正確に実行してください。
笑顔

これは試しませんでしたが、base64エンコードはASCII文字でのみ機能するという、このことに関する他の投稿を読みました。
-user984003

11

ここでは、できるだけ少ない言葉で説明します。エスケープする必要のないキャラクターに焦点を当てます:

Cookieの場合:

abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789!#$%&'()*+-./:<>?@[]^_`{|}~

URLの場合

abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789.-_~!$&'()*+,;=:@

CookieとURL(交差)の場合

abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789!$&'()*+-.:@_~

それがあなたの答えです。

Cookieの場合、=は通常Cookie値を設定するために使用されるため、削除されていることに注意してください。

URLの場合、これは=が維持されていました。交差点は明らかにありません。

var chars = "abdefghijklmnqrstuvxyz"; chars += chars.toUpperCase() + "0123456789" + "!$&'()*+-.:@_~";

特に最後の文字が検出された場合にCookieが二重引用符で囲まれるJava Cookie環境では、エスケープがまだ発生していて予期しないことが発生していることがわかります。

安全のため、A-Za-z1-9を使用してください。それが私がやろうとしていることです。


Safari Cookieが唯一の問題のあるブラウザーでした–他のすべてのブラウザーは問題なく動作しました。等号記号とスペースを処理するには、CookieをUrlEncodeおよびUrlDecodeする必要がありました。CookieのBase64Encodeのようです。(Safariはこれのみを必要としました-他のブラウザーはエンコードされたCookieの有無にかかわらず正常に機能しました。)
Sql Surfer

あなたの答えにつながっているソースをリストアップした方がいいです!
Loc 2018年

1
@Loc 3時間を超える試用と検査。
mmm

10

2011年4月に公開された新しいrfc6265

cookie-header = "Cookie:" OWS cookie-string OWS
cookie-string = cookie-pair *( ";" SP cookie-pair )
cookie-pair  = cookie-name "=" cookie-value
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

あなたが見れば@bobinceの答えは、あなたは、新しい制限がより厳しいことがわかります。


6

「;」を入れることはできません Cookieの値フィールドでは、設定される名前は「;」までの文字列です。ほとんどのブラウザで...


1

Cookie仕様には2つのバージョンがあり
ます。1.バージョン0 Cookie(別名Netscape Cookie)、
2。バージョン1(別名RFC 2965 Cookie)
バージョン0でCookie の名前と値の部分は、セミコロン、コンマ、等号、および空白を除く文字のシーケンスです。 、二重引用符で使用しない場合、
バージョン1の方がはるかに複雑です。ここで確認できます
。このバージョンでは、名前の値の部分の仕様はほぼ同じですが、名前の先頭に$記号を付けることはできません。


値はバージョン0で等号を除外する必要があるとどこに言っていますか?
Gili

1

IEとEdgeには別の興味深い問題があります。名前に1つ以上のピリオドが含まれているCookieは、通知なしにドロップされるようです。したがって、これは機能します:

cookie_name_a = valuea

これは落とされますが

cookie.name.a = valuea


ブラウザーの動作がCookieで一貫していないため、複製するために正確なブラウザーバージョンを追加すると便利です。
ジェラルド

0

それは簡単です:

<cookie-name>には、制御文字(CTL)、スペース、またはタブを除く任意のUS-ASCII文字を使用できます。また、次のような区切り文字を含めることもできません。()<> @、; :\ "/ []?= {}。

<cookie-value>はオプションで二重引用符で設定でき、CTL、空白、二重引用符、コンマ、セミコロン、およびバックスラッシュを除くUS-ASCII文字を使用できます。エンコーディング:多くの実装では、Cookie値に対してURLエンコーディングを実行しますが、RFC仕様では必須ではありません。ただし、どの文字を許可するかについての要件を満たすのに役立ちます。

リンク:https : //developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Directives


0

もう1つ検討します。私は最近、暗号化されたCookieとして変換して返すために必要なPHPスクリプトに投稿された機密データが、「安全」であると保証されたすべてのbase64値を使用するスキームを実装しました。そのため、RC4を使用してデータ項目を忠実に暗号化し、実行しました出力はbase64_encodeを介して出力され、喜んでcookieがサイトに返されました。base64でエンコードされた文字列に「+」記号が含まれるまで、テストはうまくいったようです。文字列は問題なくページcookieに書き込まれました。ブラウザ診断を使用して、 Cookieが変更されていないことを確認します。次のページが私のPHPを呼び出し、$ _ COOKIE配列を介してCookieを取得したとき、文字列に「+」記号がないことを突き止められました。その文字のすべての出現は、 ASCIIスペース。

それ以来、このシナリオの説明で読んだ同様の未解決の苦情がいくつあるかを考えると、base64を使用してCookieに任意のデータを「安全に」格納することへの言及が多いため、問題を指摘し、明らかに不器用なソリューションを提供すると思いました。

データの一部に対して実行したい暗号化をすべて実行し、base64_encodeを使用して「Cookieセーフ」にした後、出力文字列を実行します...

// from browser to PHP. substitute troublesome chars with 
// other cookie safe chars, or vis-versa.  

function fix64($inp) {
    $out =$inp;
    for($i = 0; $i < strlen($inp); $i++) {
        $c = $inp[$i];
        switch ($c) {
            case '+':  $c = '*'; break; // definitly won't transfer!
            case '*':  $c = '+'; break;

            case '=':  $c = ':'; break; // = symbol seems like a bad idea
            case ':':  $c = '='; break;

            default: continue;
            }
        $out[$i] = $c;
        }
    return $out;
    }

ここでは、エンコードされた値をCookieとして使用するためにページに返す前に、「+」(および「=」も同様に)を他の「Cookieセーフ」文字に置き換えています。処理される文字列の長さは変化しないことに注意してください。同じ(またはサイトの別のページ)がPHPスクリプトを再度実行すると、文字が欠落することなくこのCookieを回復できます。作成した同じfix64()呼び出しを介してCookieを渡すことを忘れないでください。そこから、通常のbase64_decode()を使用してデコードし、その後にスキームの他の復号化を実行できます。

Cookieで使用されているbase64文字列を破損することなくPHPに転送できるようにするために、PHPで設定できる可能性があります。その間、これは機能します。「+」は「正当な」Cookie値である可能性がありますが、そのような文字列をPHPに送信できるようにしたい場合(私の場合は$ _COOKIE配列を介して)、削除するように再処理することをお勧めします問題のある文字、および回復後にそれらを復元します。他にもたくさんの「クッキーセーフ」キャラクターから選ぶことができます。


0

後で変数を使用する場合、path実際にのようなものがアクセント付き文字を通過させることがわかりますが、実際にはブラウザーのパスと一致しません。そのためには、それらをURIEncodeする必要があります。つまり、このように:

  const encodedPath = encodeURI(myPath);
  document.cookie = `use_pwa=true; domain=${location.host}; path=${encodedPath};`

したがって、「許可された」文字は、仕様に含まれる文字数を超える可能性があります。ただし、仕様の範囲内にとどまり、URIエンコードされた文字列を使用して安全にする必要があります。


-1

数年前、MSIE 5または5.5(おそらく両方)では、HTMLブロックの "-"に深刻な問題がありました。MD5ハッシュ(文字と数字のみを含む)をCookieに保存して、サーバー側のデータベースの他のすべてを検索しているため、直接関係はありませんが。


-2

私は結局使用しました

cookie_value = encodeURIComponent(my_string);

そして

my_string = decodeURIComponent(cookie_value);

それはすべての種類のキャラクターで機能するようです。それ以外の場合は、セミコロンやコンマ以外の文字を使用しても奇妙な問題がありました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.