mirror of
https://github.com/jlengrand/vert.x.git
synced 2026-03-10 08:51:19 +00:00
Merge pull request #3202 from eclipse-vertx/issues/same-site-cookie
Proposal for same site cookie value
This commit is contained in:
@@ -26,6 +26,32 @@ Require client to present authentication, if not presented then negotiations wil
|
||||
+++
|
||||
|===
|
||||
|
||||
[[CookieSameSite]]
|
||||
== CookieSameSite
|
||||
|
||||
++++
|
||||
Represents the Cookie SameSite policy to be used. For more info <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_cookies">https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_cookies</a>.
|
||||
++++
|
||||
'''
|
||||
|
||||
[cols=">25%,75%"]
|
||||
[frame="topbot"]
|
||||
|===
|
||||
^|Name | Description
|
||||
|[[NONE]]`NONE`|+++
|
||||
The browser will send cookies with both cross-site requests and same-site requests.
|
||||
+++
|
||||
|[[STRICT]]`STRICT`|+++
|
||||
The browser will only send cookies for same-site requests (requests originating from the site that set the cookie).
|
||||
If the request originated from a different URL than the URL of the current location, none of the cookies tagged
|
||||
with the Strict attribute will be included.
|
||||
+++
|
||||
|[[LAX]]`LAX`|+++
|
||||
Same-site cookies are withheld on cross-site subrequests, such as calls to load images or frames, but will be sent
|
||||
when a user navigates to the URL from an external site; for example, by following a link.
|
||||
+++
|
||||
|===
|
||||
|
||||
[[DnsResponseCode]]
|
||||
== DnsResponseCode
|
||||
|
||||
|
||||
@@ -349,6 +349,19 @@ browser can store them.
|
||||
Cookies are described by instances of {@link io.vertx.core.http.Cookie}. This allows you to retrieve the name,
|
||||
value, domain, path and other normal cookie properties.
|
||||
|
||||
Same Site Cookies let servers require that a cookie shouldn't be sent with cross-site (where Site is defined by the
|
||||
registrable domain) requests, which provides some protection against cross-site request forgery attacks. This kind
|
||||
of cookies are enabled using the setter: {@link io.vertx.core.http.Cookie#setSameSite(CookieSameSite)}.
|
||||
|
||||
Same site cookies can have one of 3 values:
|
||||
|
||||
* None - The browser will send cookies with both cross-site requests and same-site requests.
|
||||
* Strict - he browser will only send cookies for same-site requests (requests originating from the site that set the
|
||||
cookie). If the request originated from a different URL than the URL of the current location, none of the cookies
|
||||
tagged with the Strict attribute will be included.
|
||||
* Lax - Same-site cookies are withheld on cross-site subrequests, such as calls to load images or frames, but will be
|
||||
sent when a user navigates to the URL from an external site; for example, by following a link.
|
||||
|
||||
Here's an example of querying and adding cookies:
|
||||
|
||||
[source,$lang]
|
||||
|
||||
@@ -118,6 +118,15 @@ public interface Cookie {
|
||||
@Fluent
|
||||
Cookie setHttpOnly(boolean httpOnly);
|
||||
|
||||
/**
|
||||
* Sets the same site of this cookie.
|
||||
*
|
||||
* @param policy The policy should be one of {@link CookieSameSite}.
|
||||
* @return a reference to this, so the API can be used fluently
|
||||
*/
|
||||
@Fluent
|
||||
Cookie setSameSite(CookieSameSite policy);
|
||||
|
||||
/**
|
||||
* Encode the cookie to a string. This is what is used in the Set-Cookie header
|
||||
*
|
||||
|
||||
54
src/main/java/io/vertx/core/http/CookieSameSite.java
Normal file
54
src/main/java/io/vertx/core/http/CookieSameSite.java
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
*/
|
||||
package io.vertx.core.http;
|
||||
|
||||
import io.vertx.codegen.annotations.VertxGen;
|
||||
|
||||
/**
|
||||
* Represents the Cookie SameSite policy to be used. For more info <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_cookies">https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_cookies</a>.
|
||||
*
|
||||
* @author <a href="mailto:plopes@redhat.com">Paulo Lopes</a>
|
||||
*/
|
||||
@VertxGen
|
||||
public enum CookieSameSite {
|
||||
|
||||
/**
|
||||
* The browser will send cookies with both cross-site requests and same-site requests.
|
||||
*/
|
||||
NONE("None"),
|
||||
|
||||
/**
|
||||
* The browser will only send cookies for same-site requests (requests originating from the site that set the cookie).
|
||||
* If the request originated from a different URL than the URL of the current location, none of the cookies tagged
|
||||
* with the Strict attribute will be included.
|
||||
*/
|
||||
STRICT("Strict"),
|
||||
|
||||
/**
|
||||
* Same-site cookies are withheld on cross-site subrequests, such as calls to load images or frames, but will be sent
|
||||
* when a user navigates to the URL from an external site; for example, by following a link.
|
||||
*/
|
||||
LAX("Lax");
|
||||
|
||||
/**
|
||||
* Just use a human friendly label instead of the capitalized name.
|
||||
*/
|
||||
private final String label;
|
||||
|
||||
CookieSameSite(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return label;
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import io.netty.handler.codec.http.cookie.DefaultCookie;
|
||||
import io.netty.handler.codec.http.cookie.ServerCookieDecoder;
|
||||
import io.netty.handler.codec.http.cookie.ServerCookieEncoder;
|
||||
import io.vertx.core.http.Cookie;
|
||||
import io.vertx.core.http.CookieSameSite;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -63,6 +64,8 @@ public class CookieImpl implements ServerCookie {
|
||||
private final io.netty.handler.codec.http.cookie.Cookie nettyCookie;
|
||||
private boolean changed;
|
||||
private boolean fromUserAgent;
|
||||
// extension features
|
||||
private CookieSameSite sameSite;
|
||||
|
||||
public CookieImpl(String name, String value) {
|
||||
this.nettyCookie = new DefaultCookie(name, value);
|
||||
@@ -136,9 +139,20 @@ public class CookieImpl implements ServerCookie {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cookie setSameSite(final CookieSameSite sameSite) {
|
||||
this.sameSite = sameSite;
|
||||
this.changed = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encode() {
|
||||
return ServerCookieEncoder.STRICT.encode(nettyCookie);
|
||||
if (sameSite != null) {
|
||||
return ServerCookieEncoder.STRICT.encode(nettyCookie) + "; SameSite=" + sameSite.toString();
|
||||
} else {
|
||||
return ServerCookieEncoder.STRICT.encode(nettyCookie);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isChanged() {
|
||||
|
||||
@@ -5656,6 +5656,37 @@ public abstract class HttpTest extends HttpTestBase {
|
||||
assertEquals("foo=bar; Path=/somepath; Domain=foo.com; Secure; HTTPOnly", cookie.encode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCookieSameSiteFieldEncoding() throws Exception {
|
||||
Cookie cookie = Cookie.cookie("foo", "bar").setSameSite(CookieSameSite.LAX);
|
||||
assertEquals("foo", cookie.getName());
|
||||
assertEquals("bar", cookie.getValue());
|
||||
assertEquals("foo=bar; SameSite=Lax", cookie.encode());
|
||||
|
||||
cookie.setSecure(true);
|
||||
assertEquals("foo=bar; Secure; SameSite=Lax", cookie.encode());
|
||||
cookie.setHttpOnly(true);
|
||||
assertEquals("foo=bar; Secure; HTTPOnly; SameSite=Lax", cookie.encode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCookieSameSiteFieldValidation() throws Exception {
|
||||
Cookie cookie = Cookie.cookie("foo", "bar");
|
||||
|
||||
try {
|
||||
cookie.setSameSite(CookieSameSite.LAX);
|
||||
// OK
|
||||
cookie.setSameSite(CookieSameSite.STRICT);
|
||||
// OK
|
||||
cookie.setSameSite(CookieSameSite.NONE);
|
||||
// OK
|
||||
cookie.setSameSite(null);
|
||||
// OK
|
||||
} catch (RuntimeException e) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveCookies() throws Exception {
|
||||
testCookies("foo=bar", req -> {
|
||||
|
||||
Reference in New Issue
Block a user