Sunucu tarafındaki çerezleri silmenin doğru yolu


141

Kimlik doğrulama işlemim için, kullanıcı oturum açıp kimlik doğrulama için kullanılan bir çereze koyduğunda benzersiz bir belirteç oluşturuyorum.

Yani sunucudan böyle bir şey göndermek istiyorum:

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

Hangi tüm tarayıcılarda çalışır. Daha sonra bir çerezi silmek expiresiçin, 1 Ocak 1970 için ayarlanan alanla benzer bir çerez gönderirim

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

Ve bu Firefox'ta iyi çalışıyor, ancak IE veya Safari'deki çerezi silmiyor.

Peki bir çerezi silmenin en iyi yolu nedir (tercihen JavaScript olmadan)? Son kullanma tarihi geçen yöntem hantal görünüyor. Ayrıca bu neden FF'de çalışıyor ancak IE veya Safari'de çalışmıyor?


Yanıtlar:


209

Aynı çerez değerini ; expiresekli olarak göndermek çerezleri yok etmez.

Boş bir değer ayarlayarak çerezi geçersiz kılın ve bir expiresalan da ekleyin :

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

Tüm tarayıcıları bir çerezi silmeye zorlayamayacağınızı unutmayın. İstemci, tarayıcıyı, süresi dolmuş olsa bile çerezin kalıcı olacağı şekilde yapılandırabilir. Değeri yukarıda açıklandığı gibi ayarlamak bu sorunu çözecektir.


52
"deleted"Potansiyel olarak yasal bir değere sahip karışıklıktan kaçınmak için bunun yerine boş bir metni çöp olarak kullanmanızı tavsiye ederim
yegor256

8
@raulk Evet, haklısın. Daha önce fark edilmemiş olması komik, umarım çok fazla soruna neden olmamıştır. yegor256, çoğu durumda boş bir değer çalışmalıdır. İlgili: bazı kişiler, bu başlığı gönderdikten sonra bile çerezlerinin neden kaldırılmadığını merak edebilir. Bu durumda, diğer alanlardan gelen çerezlere bir göz atın. Örneğin, sildikten sonra foo=bar; domain=www.example.combaşka bir çerez foo=qux; domain=.example.comkullanılacaktır.
Lekensteyn

3
"İstemci tarayıcıyı, süresi dolsa bile çerez kalıcı olacak şekilde yapılandırabilir. Değeri yukarıda açıklandığı gibi ayarlamak bu sorunu çözecektir." İstemci, tarayıcıyı çerez içeriğini "silindi" olarak ayarlama isteğinizi yok sayacak şekilde yapılandıramıyor mu? İstemciyi istemediği herhangi bir şeyi yapmaya zorlamanın hiçbir yolu yoktur.
Ajedi32

@ Ajedi32 Olabilir, ancak daha sonra bunu yapmak için ek çaba sarf etmeniz gerekir (müşteri olarak). Boş bir değeri göz ardı etme davranışı çok daha yaygındır, bir tarayıcının bu istekleri, özellikle geçersiz kılınan oturum kimlikleri için yoksayması mantıklı olmaz.
Lekensteyn

2
-1, çünkü bir tarayıcıyı çerez süresinin dolmasını göz ardı edecek şekilde yapılandırmanın bir yolunu görmedim ve böyle bir seçenek sunan herhangi bir tarayıcının var olduğundan emin değilim. Dahası, cevabınızın ilk cümlesi, @ DaveJarvis'in oldukça cesur düzenlemesinden sonra, şimdi herhangi bir büyük tarayıcı veya herhangi bir spec uyumlu kullanıcı aracısı için açıkça yanlıştır. tools.ietf.org/search/rfc6265#section-5.3 , "Kullanıcı aracısı, herhangi bir zamanda, çerez deposunda süresi dolmuş bir çerez varsa, süresi dolmuş tüm çerezleri çerez deposundan çıkarması GEREKİR." ve bildiğim kadarıyla her tarayıcı aslında bunu yapıyor.
Mark Amery

47

Bu yanıtı yazdığım sırada, bu soruya kabul edilen cevap , Expiresdeğeri geçmişte olan yeni bir çerez alırken tarayıcıların bir çerezi silmesi gerekmediğini belirtir . Bu iddia yanlıştır. ExpiresGeçmişte olma ayarı , bir çerezi silmenin standart, spesifikasyona uygun yoludur ve spec tarafından saygı duyulması için kullanıcı aracıları gereklidir.

ExpiresBir çerez silmek için geçmişte bir öznitelik kullanmak doğrudur ve şartname tarafından dikte edilen çerezleri kaldırmanın yoludur. RFC 6255'in örnekler bölümünde şunlar bulunur :

Son olarak, bir çerezi kaldırmak için sunucu, son kullanma tarihi geçmiş bir Set-Cookie başlığı döndürür. Sunucu, yalnızca Set-Cookie üstbilgisindeki Yol ve Etki Alanı özniteliği, çerez oluşturulduğunda kullanılan değerlerle eşleşirse çerezin kaldırılmasında başarılı olacaktır.

User Agent Gereksinimler bölümü birlikte kullanıcı aracısı olan son kullanma tarihi geçmiş bir aynı adla yeni bir çerez alırsa bir çerez hemen tamamen yok edilir gerektiğini etkisi aşağıdaki gereksinimleri içerir

  1. [Yeni bir çerez alırken] çerez deposu, yeni oluşturulan çerezle aynı ada, alana ve yola sahip bir çerez içeriyorsa:

    1. ...
    2. ...
    3. Yeni oluşturulan çerezin oluşturulma zamanını, eski çerezin oluşturulma zamanına uyacak şekilde güncelleyin.
    4. Eski çerezi çerez deposundan kaldırın.
  2. Yeni oluşturulan çerezi, çerez deposuna ekleyin.

Çerezin geçmişte bir son kullanma tarihi varsa, çerezin süresi dolmuş demektir.

Herhangi bir zamanda, çerez deposunda süresi dolmuş bir çerez varsa, kullanıcı aracısının süresi dolmuş tüm çerezleri çerez deposundan çıkarması GEREKİR.

Yukarıdaki 11-3, 11-4 ve 12. puanlar, aynı ada, alana ve yola sahip yeni bir çerez alındığında eski çerezin kaldırılması ve yeni çerezle değiştirilmesi gerektiği anlamına gelir. Son olarak, süresi dolmuş çerezlerle ilgili aşağıdaki nokta, bundan sonra, yeni çerezin de derhal boşaltılması gerektiğini belirtir . Spec, bu noktada tarayıcılara kıpır kıpır oda sunmuyor; bir tarayıcı kullanıcıya, çerezin sona erme tarihini devre dışı bırakma seçeneği sunsaydı, kabul edilen yanıt bazı tarayıcıların yaptığı gibi, o zaman bu özellik ihlal edilir. (Böyle bir özelliğin de çok az kullanımı olacaktır ve bildiğim kadarıyla herhangi bir tarayıcıda mevcut değildir.)

Öyleyse, bu sorunun OP'si neden bu yaklaşımın başarısız olduğunu gözlemledi? Ben davranışını kontrol etmek için Internet Explorer bir kopyasını tozunu olmasa da, ben OP Expiresdeğeri hatalı olduğundan şüpheleniyorum ! Bu değeri kullandılar:

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

Ancak bu sözdizimsel olarak iki şekilde geçersizdir.

Özelliğin sözdizimi bölümü , Expiresözniteliğin değerinin bir

[RFC2616], Bölüm 3.3.1'de tanımlanan rfc1123 -tarihi

Yukarıdaki ikinci bağlantıyı takiben, bu formata örnek olarak verilmiştir:

Sun, 06 Nov 1994 08:49:37 GMT

ve sözdizimi tanımının ...

  1. tarihlerin soru soran tarafından kullanılan ay gün yıl biçiminde değil, gün ay yıl biçiminde yazılmasını gerektirir .

    Özellikle, rfc1123-dateaşağıdaki gibi tanımlar :

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

    ve şöyle tanımlar date1:

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

ve

  1. UTCsaat dilimi olarak izin vermez .

    Spesifikasyon, bu formatta hangi saat dilimi ofsetlerinin kabul edilebilir olduğuna ilişkin aşağıdaki ifadeyi içerir:

    Tüm HTTP tarih / zaman damgaları istisnasız Greenwich Ortalama Saati'nde (GMT) temsil edilmelidir.

    Bu datetime formatında orijinal spec derinliklerine inin ise Dahası, biz de ilk spec bulmak https://tools.ietf.org/html/rfc822 , sözdizimi bölüm listeleri "UT" ( "evrensel saati" anlamına ) olası bir değer olarak, ancak does not listesi değildir geçerli olarak UTC (eşgüdümlü Evrensel Zaman). Bildiğim kadarıyla, bu tarih biçiminde "UTC" kullanmak hiç geçerli değildi; biçim ilk kez 1982'de belirtildiğinde geçerli bir değer değildi ve HTTP spesifikasyonu "GMT" dışındaki tüm "bölge" değerlerinin kullanımını yasaklayarak biçimin daha kısıtlayıcı bir sürümünü benimsedi .

Buradaki soru asker yerine kullanılmış olsaydı Expiresgibi niteliğini bu , o zaman:

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

o zaman muhtemelen işe yarardı.


15

"Son kullanma tarihi" ni geçmiş bir tarihe ayarlamak, bir çerezi silmenin standart yoludur.

Sorununuz büyük olasılıkla tarih biçiminin geleneksel olmamasıdır. IE muhtemelen sadece GMT bekliyor.


2

"Son kullanma tarihi" yerine Maks-Yaş = -1 kullanın. Sözdizimi konusunda daha kısa, daha az seçici ve Max-Age yine de Expires'dan önceliklidir.


-1

GlassFish Jersey JAX-RS uygulaması için ortak yöntem ile bu sorunu çözdüm tüm ortak parametreleri tanımlamaktır. En az üç parametre eşit olmalıdır: ad (= "ad"), yol (= "/") ve etki alanı (= null):

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;
}

Ve bunu çerez ayarlamak için ortak bir yol kullanın:

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

ve çerezi silmek için:

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

maxAge'ı 0 olarak ayarladığımda, Chrome'un görmezden geldiği Max-Age = 0 olan bir çerez çıkarır. In RFC 6265 bölüm 4.1.1 o "sıfırdan haneli" olarak Max-Age sözdizimini belirtir. Nedeni bu olabilir. @ JoshC13 tarafından belirtildiği gibi, bölüm 5.2.2 sıfırdan küçük veya sıfıra eşit değerleri yorumlamaktan bahseder. Bu yüzden orada kendisiyle çelişiyor ...
Matthijs Wessels

Ayrıntıları bilmiyorum, ancak çiftteki bu değerler gerçekten Chrome ve diğer tarayıcılarda çalışıyor: maxAgeInMinutes * 60, sona erme.
RoutesMaps.com

1
@MatthijsWessels İyi yakala! Biraz daha derine kazdım ve görünen çelişki aslında rfc-editor.org/errata/eid3430 adresindeki erratada belirtildiği gibi kasti . "Birlikte çalışabilirliği en üst düzeye çıkarmak" için, kullanıcı aracılarınınMax-Age temsili mümkün olan en erken tarih ve saat olarak sıfır veya negatif olarak yorumlamaları gerekir , ancak sunucuların böyle bir Max-Agedeğer göndermeleri yasaktır . Yazarlar, hem yazamadıkları mevcut istemcileri hem Max-Age=0de özellikleri yazdıkları sırada gönderen sunucuları biliyorlardı ve sorunu her iki uçtan da azaltmaya çalıştılar.
Mark Amery

@ Crimean.us Artık çoğaltamam. Belki yanlış bir şey yaptım
Matthijs Wessels

@MatthijsWessels Yoksayılma sorunu Max-Age = 0 örneğimde son kullanma tarihi ZonedDateTime.now () olarak ayarlandı. PlusMinutes (maxAgeInMinutes). MaxAgeInMinutes = 0 için geçerli tarih saatidir. Bu kod, gerçek web uygulamasında uzun süre çalışmaktadır.
RoutesMaps.com
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.