2011-01-06 42 views
11

Câu hỏi đơn giản tôi nghĩ, nhưng tôi dường như không thể tìm thấy câu trả lời.Hết hạn chuỗi trong tiêu đề cookie

Tôi viết một cookie trong một Servlet Java với lớp Cookie được gửi đến trình duyệt trong các tiêu đề phản ứng như sau:

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

tôi đang làm điều này thông qua các lớp Cookie trong Servlet 2.5 API. Tôi cần thêm "HTTPOnly" vào cuối Chuỗi này, API Servlet 2.5 không hỗ trợ. Không vấn đề gì, tôi sẽ chỉ tạo Chuỗi theo cách thủ công và nối thêm "HTTPOnly" vào cuối ...

Tuy nhiên, khi làm như vậy, thử thách mà tôi gặp phải là đặt tiêu đề "Hết hạn" ở đầu tiên nơi, tôi đã sử dụng .setMaxAge (3600), tạo ra phần "Hết hạn" của Chuỗi đó. Tuy nhiên, vì tôi không thể sử dụng lớp Cookie, tôi cần tạo giá trị của phần "Hết hạn" đó.

Về cơ bản, làm cách nào để tạo "3600" được định dạng thành "Thu, 06-Jan-2011 18:45:20 GMT"?

Lưu ý: Có lẽ tôi có thể tìm ra mẫu đúng với DateFormat, nhưng tôi đã hy vọng có cách tốt hơn để làm điều đó. Một suy nghĩ khác: Sử dụng lớp Cookie như trước đây, sau đó chỉ cần chuyển đổi Cookie thành chuỗi tiêu đề tương ứng theo chương trình, sau đó chỉ cần thêm "HTTPOnly" vào cuối. Nhưng tôi không biết cách nào để lấy đối tượng Cookie và chuyển đổi nó thành giá trị String tương ứng.

Vì vậy, tùy chọn, làm cách nào tôi có thể lấy đối tượng Cookie và chuyển đổi nó thành giá trị Chuỗi tương ứng theo chương trình?

Cảm ơn!

Trả lời

16

Something như thế này:

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

.. và vì toGMTString() bị phản đối

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); 
+0

Cảm ơn, tôi khá chắc chắn rằng phương thức "toGMTString" không được dùng nữa. – JasonStoltz

+0

ok, tôi đã cập nhật câu trả lời của mình – RealHowTo

+0

Tôi đã kết thúc bằng cách sử dụng một mẫu hơi khác (xem câu trả lời của tôi) để khớp với những gì mà thùng chứa Servlet tạo ra và tôi hy vọng tìm cách tránh sử dụng DateFormat. Tuy nhiên, điều này sẽ hoạt động và không có câu trả lời nào khác, vì vậy tôi đánh dấu câu trả lời này là câu trả lời. – JasonStoltz

6

Vâng, tôi đã không thấy hoạt động nhiều về câu hỏi này, vì vậy tôi sẽ cố gắng trả lời câu hỏi này để cung cấp trợ giúp cho bất kỳ ai tìm kiếm câu trả lời trong tương lai. Tuy nhiên, tôi sẽ để nó mở để cho người khác cơ hội nhảy vào nếu họ chọn.

Vì vậy, đã có một vài lựa chọn mà tôi coi ...

1)

Apache Commons HttpClient dự án có một lớp "DateUtil" mà tôi đã hy vọng sẽ làm việc. http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/util/DateUtil.html. Điều này cung cấp các phương thức tiện lợi để định dạng ngày thành một vài định dạng chuẩn để giao tiếp các ngày trong tiêu đề http ... tuy nhiên, không có định dạng nào trong số chúng dường như khớp chính xác với những gì đã được thùng chứa servlet trả về.

2)

Apache Commons cũng có một lớp Cookie trong dự án đó, trong đó có một "toExternalForm" phương thức trả về một String. Bằng cách đó, tôi nghĩ rằng tôi có thể chỉ cần tạo ra cookie cho mỗi bình thường, gọi "toExternalForm", sau đó nối thêm "HTTPOnly". http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/Cookie.html. Điều đó có thể làm việc, nhưng tôi không bận tâm cố gắng.

3)

Cuối cùng tôi quyết định chỉ sử dụng một mô hình phù hợp với những gì Servlet container của tôi đã trở về, cho dù đó là một định dạng chuẩn hay không. Nếu đó là những gì Servlet container trả về, thì nó sẽ hoạt động đúng không? Tại sao không ...

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

Câu trả lời đầu tiên do JasonStoltz là đúng nhất: HttpClient dự án

1) Apache Commons có một lớp "DateUtil" mà tôi đã hy vọng sẽ làm việc. http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/util/DateUtil.html. Điều này cung cấp các phương thức tiện lợi để định dạng ngày thành một vài định dạng chuẩn để giao tiếp các ngày trong tiêu đề http ... tuy nhiên, không có định dạng nào trong số chúng dường như khớp chính xác với những gì đã được thùng chứa servlet trả về.

Sử dụng thư viện DateTime để nhận đối tượng ngày trong một giờ trong tương lai (hoặc bất kỳ lúc nào), sau đó sử dụng lớp Apache DateUtil. Kết quả đầu ra của lớp đó theo RFC, do đó bạn không phải lo lắng rằng nó không khớp với những gì servlet của bạn thường tạo ra - các trình duyệt sẽ tôn trọng RFC!

Mã của bạn sẽ trông giống như thế này:

// 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) + ";"); 
+1

Tuyệt vời schimmy. Đoạn mã của bạn đặt tiêu đề "Hết hạn", không phải là "Đặt cookie". – JasonStoltz

7

Java 8 bây giờ cung cấp một định dạng ngày thích hợp, 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" 

định dạng này có giá trị cho các thuộc tính expires, xem RFC 6265 § 4.1.1, xác định định dạng là ngày RFC 1123:

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

Câu trả lời hay và chính xác. Nhưng tôi đề nghị sử dụng 'OffsetDateTime' thay vì' ZonedDateTime' để rõ ràng hơn về ý định của bạn. Chúng tôi chỉ có UTC tham gia ở đây chứ không phải là múi giờ thực sự, do đó, 'OffsetDateTime' là thích hợp.Một múi giờ thực sự là một offset-from-UTC * plus * một bộ quy tắc để xử lý các sự bất thường như Daylight Saving Time (DST). –

+0

@BasilBourque, bạn nói đúng, 'OffsetDateTime' là ngữ nghĩa chính xác hơn' ZonedDateTime', tôi đã chỉnh sửa tương ứng. – kuporific

Các vấn đề liên quan