在Cookie标头中过期字符串

时间:2011-01-06 21:38:54

标签: java cookies servlets

简单的问题我想,但我似乎无法找到答案。

我正在使用Cookie类在Java Servlet中编写一个cookie,该类在响应头中发送到浏览器,如下所示:

Set-Cookie: test=somevalue; Domain=.mydomain.org; Expires=Thu, 06-Jan-2011 18:45:20 GMT; Path=/

我是通过Servlet 2.5 API中的Cookie类来完成的。我需要在此String的末尾添加“HTTPOnly”,Servlet 2.5 API不支持。没问题,我只是手动创建String并将“HTTPOnly”追加到最后......

然而,在这样做的过程中,遇到的挑战是首先在那里设置“Expires”标题,我使用了.setMaxAge(3600),它创建了该String的“Expires”部分。但是,由于我无法使用Cookie类,因此我需要创建“Expires”部分的值。

基本上,如何将“3600”格式化为“星期四,2011年1月6日18:45:20 GMT”?

注意:我可能用DateFormat找出正确的模式,但我希望有更好的方法来做到这一点。另一个想法:像以前一样使用Cookie类,然后只是以编程方式将Cookie转换为相应的标题字符串,然后只需将“HTTPOnly”附加到结尾。但我不知道采取Cookie对象并将其转换为相应的String值的任何方法。

所以可选地,我如何获取Cookie对象并以编程方式将其转换为相应的String值?

谢谢!

4 个答案:

答案 0 :(得分:20)

这样的事情:

Date expdate = new Date ();
expdate.setTime (expdate.getTime() + (3600 * 1000));
String cookieExpire = "expires=" + expdate.toGMTString();
...

..因为不推荐使用toGMTString()

Date expdate= new Date();
expdate.setTime (expdate.getTime() + (3600 * 1000));
DateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", java.util.Locale.US);
df.setTimeZone(TimeZone.getTimeZone("GMT"));
String cookieExpire = "expires=" + df.format(expdate);

答案 1 :(得分:9)

Java 8现在提供了一个合适的日期格式化程序DateTimeFormatter.RFC_1123_DATE_TIME

OffsetDateTime oneHourFromNow 
        = OffsetDateTime.now(ZoneOffset.UTC)
        .plus(Duration.ofHours(1));

String cookieExpires 
        = DateTimeFormatter.RFC_1123_DATE_TIME
        .format(oneHourFromNow);

// E.g. "Tue, 8 Nov 2016 20:15:46 GMT"

此格式对expires属性有效,请参阅RFC 6265 § 4.1.1,其中将格式定义为RFC 1123日期:

expires-av        = "Expires=" sane-cookie-date
sane-cookie-date  = <rfc1123-date, defined in [RFC2616], Section 3.3.1>

答案 2 :(得分:6)

好吧,我在这个问题上没有看到太多活动,所以我将尝试回答这个问题,以便为将来寻找答案的人提供帮助。但是,如果他们选择的话,我会让其他人有机会参与其中。

所以我考虑了几个选项......

<强> 1)

Apache Commons HTTPClient项目有一个“DateUtil”类,我希望它可以工作。 http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/util/DateUtil.html。这提供了方便的方法,将日期格式化为几种标准格式,以便在http标头中传递日期...但是,它们似乎都没有与servlet容器返回的内容完全匹配。

<强> 2)

Apache Commons在该项目中也有一个Cookie类,它有一个返回String的“toExternalForm”方法。使用它,我想我可能只是按照惯例创建cookie,调用“toExternalForm”,然后追加“HTTPOnly”。 http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/Cookie.html。这可能有用,但我没有费心去尝试。

第3)

我最终决定使用与我的Servlet容器返回的模式匹配的模式,无论它是否是标准格式。如果它是Servlet容器返回的内容,那么它应该可以工作,对吧?为什么不......

SimpleDateFormat COOKIE_EXPIRES_HEADER_FORMAT = new SimpleDateFormat("EEE, dd-MMM-yyyy HH:mm:ss zzz");
COOKIE_EXPIRES_HEADER_FORMAT.setTimeZone(new SimpleTimeZone(0, "GMT"));
Date d = new Date();
d.setTime(d.getTime() + 3600 * 1000); //1 hour
String cookieLifeTime = COOKIE_EXPIRES_HEADER_FORMAT.format(d);
response.setHeader("Set-Cookie", "test=somevalue; Domain=.mydomain.org; Expires=" + cookieLifeTime + "; Path=/; HTTPOnly");

答案 3 :(得分:2)

JasonStoltz给出的第一个答案是正确答案:

  

1)Apache Commons HTTPClient项目有一个我希望可以工作的“DateUtil”类。 http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/util/DateUtil.html。这提供了方便的方法,将日期格式化为几种标准格式,以便在http标头中传递日期...但是,它们似乎都没有与servlet容器返回的内容完全匹配。

使用DateTime库在将来(或任何时间)获取一个小时的日期对象,然后使用Apache DateUtil类。 该类根据RFC输出,因此您不必担心它与您的servlet“通常产生的”不匹配 - 浏览器将尊重RFC

您的代码将如下所示:

// for one hour later (should probably use date libraries in general, this is somewhat awkward)
Date expiresDate = new Date(new Date().getTime() + 3600*1000); 
response.setHeader("Set-Cookie", "Expires=" + DateUtil.formatDate(expiresDate) + ";");