Do you know any Java cookie implementation which allows to set a custom flag for cookie, like SameSite=strict? It seems that javax.servlet.http.Cookie has a str
If you have existing code, no doubt you've used the java servlet Cookie object. We certainly have, so we wanted the least disruptive option. @kriegaex's answer is clean and concise, but is basically hard coding the cookie and doesn't reuse the cookie object. To expand on his answer, we wrote this function to handle the same site functionality, while at the same time, maintaining the existing Cookie object functionality. This answer is intended to be used in cases where you need to add multiple cookies on your response object, without making changes to existing cookies that may already be on the headers. The other option of course is to write a new cookie class and extend the functionality, but that requires even more changes to existing code than what we've come up with here.
Note that with this solution, only one line of existing code (per cookie) changes in order to add the same site functionality.
Sample usage:
// Existing code that doesn't change:
Cookie cookie1=new Cookie("cookie1",Util.encodeURL(id));
cookie1.setHttpOnly(false);
cookie1.setPath("/");
Cookie cookie2=new Cookie("cookie2",Util.encodeURL(id));
cookie2.setHttpOnly(false);
cookie2.setPath("/");
// Old Code that is replaced by new code
// httpResponse.addCookie(cookie1);
// httpResponse.addCookie(cookie2);
// New Code - see static helper class below
HttpService.addCookie(httpResponse, cookie1, "none");
HttpService.addCookie(httpResponse, cookie2, "Strict");
Example response headers when using cURL:
< HTTP/1.1 200 OK
< Connection: keep-alive
< X-Powered-By: Undertow/1
< Set-Cookie: cookie1=f871c026e8eb418c9c612f0c7fe05b08; path=/; SameSite=none; secure
< Set-Cookie: cookie2=51b405b9487f4487b50c80b32eabcc24; path=/; SameSite=Strict; secure
< Server: WildFly/9
< Transfer-Encoding: chunked
< Content-Type: image/png
< Date: Tue, 10 Mar 2020 01:55:37 GMT
And finally, the static helper class:
public class HttpService {
private static final FastDateFormat expiresDateFormat= FastDateFormat.getInstance("EEE, dd MMM yyyy HH:mm:ss zzz", TimeZone.getTimeZone("GMT"));
public static void addCookie(HttpServletResponse response, Cookie cookie, String sameSite) {
StringBuilder c = new StringBuilder(64+cookie.getValue().length());
c.append(cookie.getName());
c.append('=');
c.append(cookie.getValue());
append2cookie(c,"domain", cookie.getDomain());
append2cookie(c,"path", cookie.getPath());
append2cookie(c,"SameSite", sameSite);
if (cookie.getSecure()) {
c.append("; secure");
}
if (cookie.isHttpOnly()) {
c.append("; HttpOnly");
}
if (cookie.getMaxAge()>=0) {
append2cookie(c,"Expires", getExpires(cookie.getMaxAge()));
}
response.addHeader("Set-Cookie", c.toString());
}
private static String getExpires(int maxAge) {
if (maxAge<0) {
return "";
}
Calendar expireDate = Calendar.getInstance();
expireDate.setTime(new Date());
expireDate.add(Calendar.SECOND,maxAge);
return expiresDateFormat.format(expireDate);
}
private static void append2cookie(StringBuilder cookie, String key, String value) {
if (key==null ||
value==null ||
key.trim().equals("")
|| value.trim().equals("")) {
return;
}
cookie.append("; ");
cookie.append(key);
cookie.append('=');
cookie.append(value);
}
}