Java 应用程序中的 SameSite cookie
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42717210/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
SameSite cookie in Java application
提问by Michal_Szulc
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 strictly limited set of flags which can be added.
您是否知道任何允许为 cookie 设置自定义标志的 Java cookie 实现,例如SameSite=strict
?似乎javax.servlet.http.Cookie
可以添加一组严格限制的标志。
采纳答案by kriegaex
I am not a JEE expert, but I think that because that cookie property is a somewhat new invention, you cannot expect it to be present in Java EE 7 interfaces or implementations. The Cookie
class is missing a setter for generic properties, as it seems. But instead of adding the cookie to your HttpServletResponse
via
我不是 JEE 专家,但我认为因为 cookie 属性是一个有点新的发明,您不能指望它出现在 Java EE 7 接口或实现中。本Cookie
类缺少通用性的制定者,因为它似乎。但不是将 cookie 添加到您的HttpServletResponse
via
response.addCookie(myCookie)
you can simply set the corresponding HTTP header field via
您可以简单地通过设置相应的 HTTP 标头字段
response.setHeader("Set-Cookie", "key=value; HttpOnly; SameSite=strict")
Update:Thanks to @mwyrzykfor pointing out that setHeader()
overwrites all existing headers of the same name. So if you happen have other Set-Cookie
headers in your response already, of course you would use addHeader()
with the same parameters instead.
更新:感谢@mwyrzyk指出它会setHeader()
覆盖所有现有的同名标头。因此,如果您Set-Cookie
的响应中已经有其他标头,当然您可以使用addHeader()
相同的参数。
回答by Marty Aghajanyan
If you don't wanna update all your code, you can also achieve same by one line config using Apache or Nginx configuration(or any other HTTP server/proxy that you are using)
如果您不想更新所有代码,您也可以使用 Apache 或 Nginx 配置(或您正在使用的任何其他 HTTP 服务器/代理)通过一行配置来实现相同的功能
1 Setting SameSite cookies using Apache configuration
1 使用 Apache 配置设置 SameSite cookie
You can add the following line to your Apache configuration
您可以将以下行添加到您的 Apache 配置中
Header always edit Set-Cookie (.*) "; SameSite=Lax"
and this will update all your cookies with SameSite=Lax
flag
这将使用SameSite=Lax
标志更新您的所有 cookie
See more here: https://blog.giantgeek.com/?p=1872
在此处查看更多信息:https: //blog.giantgeek.com/?p=1872
2 Setting SameSite cookies using Nginx configuration
2 使用 Nginx 配置设置 SameSite cookie
location / {
# your usual config ...
# hack, set all cookies to secure, httponly and samesite (strict or lax)
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
}
Same here, this also will update all your cookies with SameSite=Lax
flag
同样在这里,这也将使用SameSite=Lax
标志更新您的所有 cookie
See more here: https://serverfault.com/questions/849888/add-samesite-to-cookies-using-nginx-as-reverse-proxy
在此处查看更多信息:https: //serverfault.com/questions/849888/add-samesite-to-cookies-using-nginx-as-reverse-proxy
回答by Alexander Martyushov
As of today (24.01.20) servlet-api
does not let to set sameSite
attribute to the cookie. BTW there is an ongoing ticket (LINK) which will release a new (5.0 or 5.1 servlet-api
).
截至今天 (24.01.20)servlet-api
不允许将sameSite
属性设置为 cookie。顺便说一句,有一张正在进行的票证(LINK)将发布新的(5.0 或 5.1 servlet-api
)。
Option 1:You are not in a hurry and can wait for servlet-api
version, where Cookie
class and SessionCookieConfig
class have dedicated methods to set sameSite
attribute.
方案一:不急,可以等servlet-api
版本,Cookie
类和SessionCookieConfig
类都有专门的方法设置sameSite
属性。
Option 2:You are using an old version of servlet-api
(e.g. 3.1), consequently old version of Tomcat (e.g. I am having current situation now). It means even when community releases servlet-api
with sameSite
support, you can not immediately update you version, because it can be too risky to update couple of major versions.
In this case we have found a solution.
There is a Cookie Processor Component
LINKin Tomcat, which
选项 2:您使用的是旧版本servlet-api
(例如 3.1),因此是旧版本的 Tomcat(例如我现在处于当前情况)。这意味着,即使社会发布servlet-api
与sameSite
支持,系统无法实时更新你的版本,因为它可以是太冒险了更新几个主要的版本。
在这种情况下,我们找到了解决方案。Tomcat里面
有个Cookie Processor Component
LINK,里面有
The CookieProcessor element represents the component that parses received cookie headers into javax.servlet.http.Cookie objects accessible through HttpServletRequest.getCookies() and converts javax.servlet.http.Cookie objects added to the response through HttpServletResponse.addCookie() to the HTTP headers returned to the client.
CookieProcessor 元素表示将接收到的 cookie 标头解析为可通过 HttpServletRequest.getCookies() 访问的 javax.servlet.http.Cookie 对象并将通过 HttpServletResponse.addCookie() 添加到响应中的 javax.servlet.http.Cookie 对象转换为 HTTP 的组件标头返回给客户端。
The usage of this processor is quite straight forward. Inside of context.xml:
该处理器的使用非常简单。在 context.xml 中:
<Context>
...
<CookieProcessor sameSiteCookies="none"/>
</Context>
In this case default implementation of processor is used (org.apache.tomcat.util.http.Rfc6265CookieProcessor
), but you can specify any other within an CookieProcessor
attribute className
.
在这种情况下,使用处理器的默认实现 ( org.apache.tomcat.util.http.Rfc6265CookieProcessor
),但您可以在CookieProcessor
属性中指定任何其他实现className
。
回答by vjrngn
jetty server version 9.4.26.v20200117
allows for setting the SameSite
attribute on the cookie. I had to do some digging around but this works.
码头服务器版本9.4.26.v20200117
允许SameSite
在 cookie 上设置属性。我不得不做一些挖掘,但这有效。
import static org.eclipse.jetty.http.HttpCookie.SAME_SITE_STRICT_COMMENT;
...
Cookie cookie = new Cookie("my-cookie", "some-value");
cookie.setMaxAge(120); // age in seconds
cookie.setSecure(true);
cookie.setHttpOnly(true);
cookie.setComment(SAME_SITE_STRICT_COMMENT);
response.addCookie(cookie);
The addCookie()
method on jetty servers's Response
object does a check on the comment to add the SameSite
attribute.
该addCookie()
码头服务器对方法Response
对象不会对评论进行检查添加的SameSite
属性。
回答by wryan
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.
如果您有现有代码,无疑您已经使用过 java servlet Cookie 对象。我们当然有,所以我们想要破坏性最小的选择。@kriegaex 的回答简洁明了,但基本上是对 cookie 进行硬编码,并且不重用 cookie 对象。为了扩展他的回答,我们编写了这个函数来处理相同的站点功能,同时维护现有的 Cookie 对象功能。此答案旨在用于需要在响应对象上添加多个 cookie 的情况,而无需更改可能已在标头上的现有 cookie。当然,另一种选择是编写一个新的 cookie 类并扩展功能,但这需要对现有代码进行比我们在这里提出的更多更改。
Note that with this solution, only one line of existing code (per cookie) changes in order to add the same site functionality.
请注意,使用此解决方案,只需更改一行现有代码(每个 cookie)即可添加相同的站点功能。
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:
使用 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);
}
}
回答by Fred Andrews
I found that our cookies which were being created on a successful return were not changed by "Header edit" or "Header always edit". Apparently apache has two buckets of cookies - see this
我发现我们在成功返回时创建的 cookie 没有被“标题编辑”或“标题始终编辑”更改。显然 apache 有两桶 cookie - 看这个
What did work for me was
对我有用的是
Header onsuccess edit Set-Cookie (.*) "; SameSite=Lax"
回答by varunsinghal65
I tried the listed solutions for using javax.servlet.http.Cookie
to set the SameSite=strict
attribute, but none of them worked.
我尝试了用于javax.servlet.http.Cookie
设置SameSite=strict
属性的列出的解决方案,但没有一个有效。
However, this way worked for me, using javax.servlet.http.Cookie
(JRE 1.8 + JBOSS 7.X) :
但是,这种方式对我javax.servlet.http.Cookie
有用,使用(JRE 1.8 + JBOSS 7.X) :
Cookie cookie = new Cookie(name, value);
path = path.concat(" SameSite=Strict;");
cookie.setPath(path);
That's it. tested on
就是这样。测试
- Google Chrome Version 81.0.4044.129 (Official Build) (64-bit)
- Microsoft Edge Version 81.0.416.68 (Official build) (64-bit)
- Firefox 75.0 (64-bit)
- Google Chrome 版本 81.0.4044.129(官方版本)(64 位)
- Microsoft Edge 版本 81.0.416.68(官方版本)(64 位)
- 火狐 75.0(64 位)