Spring: невозможно установить для cookie SameSite значение None

Я не могу установить значение cookie SameSite на None.

Вот как я создаю объект ResponseCookie.

ResponseCookie cookie = ResponseCookie.from("Hb", cookieUserId)
            .maxAge(!isEmpty(cookieUserId) ? MAX_COOKIE_DURATION : 0)
            .domain("test.com")
            .sameSite("None")
            .secure(true)
            .path("/")
            .build();
 response.addCookie(cookie)

Завершение запроса к конечной точке

curl -X POST "localhost:8080/v1/user/v" --data "{}" -v -H 'Content-Type: application/json'

Отклик:

< set-cookie: Hb=00b7be31-fc6d-4891-a07c-46b5ef2b423c; Max-Age=7776000; Expires=Fri, 8 Nov 2019 17:23:52 GMT; Path=/; Domain=test.com; Secure

Как вы можете видеть атрибут SameSite отсутствует в куки.

Зависимость Spring Boot (версия: 2.1.3.RELEASE)

        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

2 ответа

Я думаю, что проблема заключается в том, что основной javax.servlet.http.Cookie не поддерживает SameSite атрибут, не говоря уже о новом None стоимость.

Вместо этого вы можете установить это непосредственно в качестве заголовка, предполагая, что ваш ответ является экземпляром javax.servlet.http.HttpServletResponse:

ResponseCookie cookie = ResponseCookie.from("Hb", cookieUserId)
            .maxAge(!isEmpty(cookieUserId) ? MAX_COOKIE_DURATION : 0)
            .domain("test.com")
            .sameSite("None")
            .secure(true)
            .path("/")
            .build();
 response.addHeader('Set-Cookie', cookie.toString());

Вот решение, использующее ваше собственное CookieSerializer боб. Вы можете просто добавить это в свой класс BootApplication:

@Bean
public CookieSerializer cookieSerializer() {
    DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
    cookieSerializer.setSameSite("None");
    return cookieSerializer;
}

Однако это переопределит атрибуты весенней сессии по умолчанию, такие как server.servlet.session.cookie.name и maxAge server.servlet.session.cookie.max-age, Итак, более полное решение выглядит так:

...
@Autowired
private CookieConfiguration cookieConfiguration;

@Bean
public CookieSerializer cookieSerializer() {
    DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
    cookieSerializer.setSameSite("None");
    cookieSerializer.setCookieName(cookieConfiguration.getName());
    cookieSerializer.setDomainName(cookieConfiguration.getDomain());
    cookieSerializer.setCookiePath(cookieConfiguration.getPath());
    cookieSerializer.setUseHttpOnlyCookie(cookieConfiguration.isHttpOnly());
    cookieSerializer.setUseSecureCookie(cookieConfiguration.isSecure());
    cookieSerializer.setCookieMaxAge((Long.valueOf(cookieConfiguration.getMaxAge().toSeconds())).intValue());
    // TODO check if rememberMeServices need additional configuration here

    return cookieSerializer;
}

И Класс Конфигурации.

@ConfigurationProperties(prefix = "server.servlet.session.cookie")
@Configuration("cookieProperties")
@Getter
@Setter
public class CookieConfiguration {

    private String comment;
    private String domain;
    private boolean httpOnly;
    private Duration maxAge;
    private String name;
    private String path;
    private boolean secure;

}

Я не уверен, что есть лучшее решение, чтобы применить свойства конфигурации и переопределить только samesite приписывать. Я могу представить, что в будущей весенней загрузочной версии эта опция / свойство будет включена. Также, как вы видите в комментарии к коду TODO, я не тестировал это решение с активными сервисами запомнить. Решение было протестировано в весенней загрузочной версии 2.1.6.RELEASE и вдохновлять от кода, найденного в org/springframework/boot/autoconfigure/session/SessionAutoConfiguration.class,

Вы можете настроить SameSite через TomcatContextCustomizer:

@Configuration
public class MvcConfiguration implements WebMvcConfigurer {

  @Bean
  public TomcatContextCustomizer sameSiteCookiesConfig() {
    return context -> {
        final Rfc6265CookieProcessor cookieProcessor = new Rfc6265CookieProcessor();
        cookieProcessor.setSameSiteCookies(SameSiteCookies.NONE.getValue());
        context.setCookieProcessor(cookieProcessor);
    };
  }

Файлы cookie для межсайтового использования должны указывать SameSite=None; Secureдля включения включения в сторонний контекст (https://web.dev/samesite-cookie-recipes/).

Ответ LukeSolar был правильным. DefaultCookieSerializer находится в spring-session jar, поэтому вам нужно добавить spring-sessionзависимости. Вы можете обратиться к официальной документации https://spring.io/projects/spring-session

Другие вопросы по тегам