Истекает строка в заголовке файла cookie - PullRequest
13 голосов
/ 07 января 2011

Простой вопрос, я думаю, но я просто не могу найти ответ.

Я пишу cookie в сервлете Java с классом Cookie, который отправляется в браузер в заголовках ответов, напримерследующее:

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

Я делаю это через класс Cookie в Servlet 2.5 API.Мне нужно добавить «HTTPOnly» в конец этой строки, которую не поддерживает API Servlet 2.5.Нет проблем, я просто создаю String вручную и добавляю «HTTPOnly» до конца ...

Однако при этом я столкнулся с проблемой, заключающейся в том, чтобы установить там заголовок «Expires» вВо-первых, я использовал .setMaxAge (3600), который создает часть «Stires» этой строки.Однако, так как я не могу использовать класс Cookie, мне нужно создать значение этой части «Expires».

Итак, в общем, как я могу сделать «3600» отформатированным в «Thu,06-Янв-2011 18:45:20 GMT "?

Примечание: я мог бы определить правильный шаблон с DateFormat, но я надеялся, что есть лучший способ сделать это.Еще одна мысль: используйте класс Cookie, как и раньше, затем просто программно конвертируйте Cookie в соответствующую строку заголовка, а затем просто добавьте «HTTPOnly» в конец.Но я не знаю ни одного способа взять объект Cookie и преобразовать его в соответствующее строковое значение.

Итак, при желании, как я могу взять объект Cookie и преобразовать его в соответствующее строковое значение программно?

Спасибо!

Ответы [ 4 ]

22 голосов
/ 07 января 2011

Примерно так:

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);
9 голосов
/ 08 ноября 2016

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 & sect; 4.1.1 , который определяет формат даты RFC 1123:

expires-av        = "Expires=" sane-cookie-date
sane-cookie-date  = <rfc1123-date, defined in [RFC2616], Section 3.3.1>
6 голосов
/ 07 января 2011

Ну, я не видел большой активности по этому вопросу, поэтому я попытаюсь ответить на него, чтобы оказать помощь любому, кто ищет ответ в будущем. Тем не менее, я оставлю это открытым, чтобы дать другим возможность участвовать, если они захотят.

Так что было несколько вариантов, которые я рассмотрел ...

1)

В проекте Apache Commons HTTPClient есть класс DateUtil, который, как я надеялся, сработает. http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/util/DateUtil.html. Это обеспечивает удобные методы для форматирования даты в несколько стандартных форматов для передачи дат в заголовках http ... однако ни один из них, похоже, не соответствует в точности тому, что возвращал контейнер сервлета.

2)

Apache Commons также имеет класс Cookie в этом проекте, у которого есть метод "toExternalForm", который возвращает String. Пользуясь этим, я подумал, что, возможно, смог создать обычный файл cookie, вызвать «toExternalForm», а затем добавить «HTTPOnly». http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/Cookie.html. Это может сработать, но я не стал пытаться.

3)

Я наконец решил просто использовать шаблон, который соответствовал тому, что возвращал мой контейнер сервлета, независимо от того, был ли это стандартный формат или нет. Если это то, что возвращает контейнер сервлетов, то он должен работать, верно? Почему бы не ...

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");
2 голосов
/ 06 марта 2013

Первый ответ, данный JasonStoltz, является правильным:

1) В проекте Apache Commons HTTPClient есть класс DateUtil, который, как я надеялся, сработает.http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/util/DateUtil.html. Это предоставляет удобные методы для форматирования даты в несколько стандартных форматов для передачи дат в заголовках http ... однако ни один из них, похоже, не соответствует точно тому, что возвращал контейнер сервлета.

Используйте библиотеку DateTime, чтобы получить объект даты на один час в будущем (или в любое другое время), а затем используйте класс Apache DateUtil. Этот класс выводит в соответствии с RFC, так что вам не нужно беспокоиться о том, что он не соответствует тому, что обычно генерирует ваш сервлет - браузеры будут соблюдать 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) + ";");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...