Подтвердить что ты не робот

Истекает строку в заголовке файла cookie

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

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

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

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

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

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

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

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

Спасибо!

4b9b3361

Ответ 1

Что-то вроде этого:

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");
df.setTimeZone(TimeZone.getTimeZone("GMT"));
String cookieExpire = "expires=" + df.format(expdate);

Ответ 2

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>

Ответ 3

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

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

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", который возвращает строку. Используя это, я подумал, что, возможно, мне удалось создать 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");

Ответ 4

Первый ответ, данный 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) + ";");