サーバー側のCookieを削除する正しい方法


141

私の認証プロセスでは、ユーザーがログインしたときに一意のトークンを作成し、認証に使用されるCookieに入れます。

したがって、サーバーから次のようなものを送信します。

Set-Cookie: token=$2a$12$T94df7ArHkpkX7RGYndcq.fKU.oRlkVLOkCBNrMilaSWnTcWtCfJC; path=/;

これはすべてのブラウザで動作します。次に、Cookieを削除するために、expires1970年1月1日に設定されたフィールドを持つ同様のCookieを送信します。

Set-Cookie: token=$2a$12$T94df7ArHkpkX7RGYndcq.fKU.oRlkVLOkCBNrMilaSWnTcWtCfJC; path=/; expires=Thu, Jan 01 1970 00:00:00 UTC; 

また、Firefoxでは正常に機能しますが、IEまたはSafariではCookieは削除されません。

では、Cookieを削除する最良の方法は何ですか(できればJavaScriptなしで)?set-the-expires-in-the-pastメソッドはかさばると思われます。また、なぜこれはFFでは機能するがIEまたはSafariでは機能しないのですか?


回答:


208

同じCookie値を; expires追加して送信しても、Cookieは破棄されません。

空の値を設定してCookieを無効にし、expiresフィールドも含めます。

Set-Cookie: token=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT

すべてのブラウザにCookieの削除を強制することはできないことに注意してください。クライアントは、有効期限が切れていてもCookieが存続するようにブラウザーを構成できます。上記のように値を設定すると、この問題が解決します。


52
"deleted"後で代わりに、空のテキストをゴミとして使用することをお勧めします。これにより、正当な値が "deleted"と等しい場合の混乱を避けることができます
yegor256

8
@raulkはい、あなたは正しいです。以前気づかなかったことはおかしいですが、うまくいけば、あまり問題は発生しませんでした。yegor256、ほとんどの場合、空の値で機能します。関連:このヘッダーを送信した後でもCookieが削除されない理由を不思議に思う人もいるでしょう。その場合は、他のドメインのCookieを確認してください。たとえば、を削除するfoo=bar; domain=www.example.comと、他のCookie foo=qux; domain=.example.comが使用されます。
Lekensteyn 2013年

3
「クライアントは、有効期限が切れていてもCookieが存続するようにブラウザーを構成できます。上記のように値を設定すると、この問題が解決します。」クライアントは、Cookieの内容を「削除済み」に設定するリクエストも無視するようにブラウザを構成できませんでしたか?クライアントに不要なことを強制する方法はありません。
Ajedi32 2015

@ Ajedi32可能ですが、その場合は(クライアントとして)追加の作業を行う必要があります。空の値を無視する動作はより一般的です。特に無効化されたセッションIDの場合、ブラウザがそのような要求を無視することは意味がありません。
Lekensteyn

2
なぜなら、私はCookieの有効期限を無視するようにブラウザーを構成する方法を見たことがなく、そのようなオプションを提供するブラウザーが存在することを確信していないからです。さらに、@ DaveJarvisのかなり大胆な編集後の回答の最初の文は、主要なブラウザや仕様に準拠したユーザーエージェントに対してまったく誤りです。tools.ietf.org/search/rfc6265#section-5.3は「いつでも、期限切れのCookieがCookieストアに存在する場合、ユーザーエージェントは、期限切れのCookieをすべてCookieストアから削除する必要がある」と述べています。そして、私の知る限りでは、すべてのブラウザが実際に行っていることです。
マークアメリー2018

46

私がこの回答を書いている時点で、この質問に対する受け入れられた回答Expiresは、値が過去の置換Cookieを受け取ったときにブラウザがCookieを削除する必要がないことを述べているようです。その主張は誤りです。Expires過去の設定は、Cookieを削除する標準の仕様に準拠した方法であり、ユーザーエージェントはそれを尊重するために仕様で必要です。

使用しExpiresたクッキーを削除するには、過去に属性は正しく、仕様によって決まるクッキーを削除する方法です。RFC 6255の例のセクションでは、次のように述べています。

最後に、Cookieを削除するために、サーバーは過去の有効期限のあるSet-Cookieヘッダーを返します。サーバーは、Set-Cookieヘッダーのパスとドメイン属性がCookieの作成時に使用された値と一致する場合にのみ、Cookieの削除に成功します。

ユーザーエージェントの要件のセクションでは、一緒に、ユーザーエージェントは、その有効期限、過去にある同じ名前を持つ新しいクッキーを受信した場合、クッキーはすぐに消去されなければならないという効果があり、次の要件を備えて

  1. [新しいCookieを受け取ったとき] Cookieストアに、新しく作成されたCookieと同じ名前、ドメイン、パスのCookieが含まれている場合:

    1. ...
    2. ...
    3. 新しく作成されたCookieの作成時刻を更新して、古いCookieの作成時刻と一致させます。
    4. cookieストアから古いcookieを削除します。
  2. 新しく作成したCookieをCookieストアに挿入します。

Cookieの有効期限が過去の場合、Cookieは「期限切れ」になります。

いつでも、期限切れのCookieがCookieストアに存在する場合、ユーザーエージェントは、期限切れのすべてのCookieをCookieストアから削除する必要があります。

上記のポイント11-3、11-4、および12は、同じ名前、ドメイン、およびパスで新しいCookieを受信したときに、古いCookieを消去して新しいCookieで置き換える必要があることを意味します。最後に、有効期限が切れたCookieに関する以下の点は、それが行われた後、新しい Cookie すぐに削除する必要があることを示しています。この点に関して、この仕様ではブラウザーに余計な余地はありません。ブラウザがCookieの有効期限を無効にするオプションをユーザーに提供する場合、受け入れられた回答が一部のブラウザがそうであるように示唆するように、それは仕様に違反しています。(このような機能もほとんど役に立ちません。私が知る限り、それはどのブラウザーにも存在しません。)

では、なぜこの質問のOPは、このアプローチの失敗を観察したのでしょうか。私はその動作を確認するためにInternet Explorerのコピーを振り払っていませんが、それはOPのExpires値が不正であったためだと思います!彼らはこの値を使用しました:

expires=Thu, Jan 01 1970 00:00:00 UTC;

ただし、これは2つの点で構文的に無効です。

仕様の構文セクションでは、Expires属性の値は

rfc1123 -date、[RFC2616]、セクション3.3.1で定義

上記の2番目のリンクをたどると、これはフォーマットの例として与えられていることがわかります。

Sun, 06 Nov 1994 08:49:37 GMT

そして、構文の定義を見つけます...

  1. 日付が書き込まれている必要があり日月年の形式ではなく、月日年の質問アスカーで使用される形式。

    具体的にはrfc1123-date、次のように定義します。

    rfc1123-date = wkday "," SP date1 SP time SP "GMT"
    

    date1このように定義します:

    date1        = 2DIGIT SP month SP 4DIGIT
                 ; day month year (e.g., 02 Jun 1982)
    

そして

  1. UTCタイムゾーンとしては許可されません。

    仕様には、この形式で許容されるタイムゾーンオフセットに関する次のステートメントが含まれています。

    すべてのHTTP日付/タイムスタンプは、例外なくグリニッジ標準時(GMT)で表す必要があります。

    さらに、この日時形式の元の仕様をさらに掘り下げると、https://tools.ietf.org/html/rfc822の最初の仕様で、構文セクションに "UT"( "universal time"を意味する)がリストされていることがわかります)可能な値として、しかしUTC(協定世界時)を有効としてリストしていませ。私の知る限り、この日付形式で「UTC」を使用することは有効ではありませんでした。1982年にフォーマットが最初に指定されたときは有効な値ではありませんでした。HTTP仕様では、「GMT」以外のすべての「ゾーン」値の使用を禁止することにより、フォーマットの厳密制限バージョンを採用しています。

ここで質問者Expiresこのような属性を代わりに使用した場合、次のようになります。

expires=Thu, 01 Jan 1970 00:00:00 GMT;

それからそれはおそらく働いたでしょう。


15

「expires」を過去の日付に設定することが、Cookieを削除する標準的な方法です。

あなたの問題はおそらく日付形式が従来のものではないためです。IEはおそらくGMTのみを想定しています。



-1

GlassFish Jersey JAX-RS実装の場合、私はこの問題を一般的な方法で解決しましたが、すべての一般的なパラメーターを説明しています。name(= "name")、path(= "/")、およびdomain(= null)の少なくとも3つのパラメータは等しくなければなりません。

public static NewCookie createDomainCookie(String value, int maxAgeInMinutes) {
    ZonedDateTime time = ZonedDateTime.now().plusMinutes(maxAgeInMinutes);
    Date expiry = time.toInstant().toEpochMilli();
    NewCookie newCookie = new NewCookie("name", value, "/", null, Cookie.DEFAULT_VERSION,null, maxAgeInMinutes*60, expiry, false, false);
    return newCookie;
}

そして、それをcookieを設定する一般的な方法で使用します。

NewCookie domainNewCookie = RsCookieHelper.createDomainCookie(token, 60);
Response res = Response.status(Response.Status.OK).cookie(domainNewCookie).build();

そしてクッキーを削除するには:

NewCookie domainNewCookie = RsCookieHelper.createDomainCookie("", 0);
Response res = Response.status(Response.Status.OK).cookie(domainNewCookie).build();

私にとってmaxAgeを0に設定すると、Chromeが無視するように見えるMax-Age = 0のCookieを出力します。ではRFC 6265のセクション4.1.1には、「非ゼロ桁」とマックス・エイジの構文を指定します。それが理由かもしれません。ただし、@ JoshC13で述べたように、セクション5.2.2はゼロ以下の値の解釈について述べています。だからそれはそこでそれ自体の一種の矛盾...
Matthijs Wessels '30

詳細はわかりませんが、これらのペアの値はChromeと他のブラウザで実際に機能しています:maxAgeInMinutes * 60、有効期限。
RoutesMaps.com 2018

1
@MatthijsWesselsグッドキャッチ!rfc-editor.org/errata/eid3430のエラッタに記載されているように、私は少し深く掘り下げましたが、明らかな矛盾は実際には意図的なものです。「相互運用性を最大化」するには、ユーザーエージェントはゼロまたは負の値Max-Ageを最も早い表現可能な日時として解釈する必要がありますが、サーバーはそのようなMax-Age値を送信できません。作成者Max-Age=0は、仕様を作成した時点で処理できなかった既存のクライアントとそれを送信したサーバーの両方を知っていて、両端から問題を軽減しようとしたと思います。
マークアメリー2018

@ Crimean.us私ももう再現できません。多分私は何か間違ったことをしました
Matthijs Wessels

@MatthijsWessels無視のMax-Age = 0の問題は、私の例では有効期限をZonedDateTime.now()。plusMinutes(maxAgeInMinutes)に設定することで修正されています。maxAgeInMinutes = 0の場合、現在の日時です。このコードは、実際のWebアプリケーションで長時間動作します。
RoutesMaps.com
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.