Skip to content

Commit

Permalink
Add SameSite session cookie config property for WebFlux
Browse files Browse the repository at this point in the history
This commit adds a new `spring.webflux.session.cookie.same-site`
confuguration property that sets the default value for the "SameSite"
attribute in the WebFlux session cookies.

Closes gh-20970
  • Loading branch information
bclozel committed Apr 6, 2021
1 parent 5b11109 commit dc6b5ba
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@
import org.springframework.web.server.i18n.AcceptHeaderLocaleContextResolver;
import org.springframework.web.server.i18n.FixedLocaleContextResolver;
import org.springframework.web.server.i18n.LocaleContextResolver;
import org.springframework.web.server.session.CookieWebSessionIdResolver;
import org.springframework.web.server.session.DefaultWebSessionManager;
import org.springframework.web.server.session.WebSessionManager;

/**
* {@link EnableAutoConfiguration Auto-configuration} for {@link EnableWebFlux WebFlux}.
Expand Down Expand Up @@ -302,6 +305,17 @@ public LocaleContextResolver localeContextResolver() {
return localeContextResolver;
}

@Bean
@ConditionalOnMissingBean(name = WebHttpHandlerBuilder.WEB_SESSION_MANAGER_BEAN_NAME)
public WebSessionManager webSessionManager() {
DefaultWebSessionManager webSessionManager = new DefaultWebSessionManager();
CookieWebSessionIdResolver webSessionIdResolver = new CookieWebSessionIdResolver();
webSessionIdResolver.addCookieInitializer((cookie) -> cookie
.sameSite(this.webFluxProperties.getSession().getCookie().getSameSite().attribute()));
webSessionManager.setSessionIdResolver(webSessionIdResolver);
return webSessionManager;
}

}

@Configuration(proxyBeanMethods = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public class WebFluxProperties {

private final Format format = new Format();

private final Session session = new Session();

/**
* Path pattern used for static resources.
*/
Expand Down Expand Up @@ -65,6 +67,10 @@ public Format getFormat() {
return this.format;
}

public Session getSession() {
return this.session;
}

public String getStaticPathPattern() {
return this.staticPathPattern;
}
Expand Down Expand Up @@ -116,4 +122,62 @@ public void setDateTime(String dateTime) {

}

public static class Session {

private final Cookie cookie = new Cookie();

public Cookie getCookie() {
return this.cookie;
}

}

public static class Cookie {

/**
* SameSite attribute value for session Cookies.
*/
private SameSite sameSite = SameSite.LAX;

public SameSite getSameSite() {
return this.sameSite;
}

public void setSameSite(SameSite sameSite) {
this.sameSite = sameSite;
}

}

public enum SameSite {

/**
* Cookies are sent in both first-party and cross-origin requests.
*/
NONE("None"),

/**
* Cookies are sent in a first-party context, also when following a link to the
* origin site.
*/
LAX("Lax"),

/**
* Cookies are only sent in a first-party context (i.e. not when following a link
* to the origin site).
*/
STRICT("Strict");

private final String attribute;

SameSite(String attribute) {
this.attribute = attribute;
}

public String attribute() {
return this.attribute;
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -1766,6 +1766,10 @@
"description": "Whether to enable Spring's HiddenHttpMethodFilter.",
"defaultValue": false
},
{
"name": "spring.webflux.session.cookie.same-site",
"defaultValue": "lax"
},
{
"name": "spring.webservices.wsdl-locations",
"type": "java.util.List<java.lang.String>",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,12 @@
import org.springframework.web.reactive.result.view.ViewResolutionResultHandler;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebSession;
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
import org.springframework.web.server.i18n.AcceptHeaderLocaleContextResolver;
import org.springframework.web.server.i18n.FixedLocaleContextResolver;
import org.springframework.web.server.i18n.LocaleContextResolver;
import org.springframework.web.server.session.WebSessionManager;
import org.springframework.web.util.pattern.PathPattern;

import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -122,6 +125,8 @@ void shouldCreateDefaultBeans() {
assertThat(context).getBeans(RequestMappingHandlerAdapter.class).hasSize(1);
assertThat(context).getBeans(RequestedContentTypeResolver.class).hasSize(1);
assertThat(context).getBeans(RouterFunctionMapping.class).hasSize(1);
assertThat(context.getBean(WebHttpHandlerBuilder.WEB_SESSION_MANAGER_BEAN_NAME, WebSessionManager.class))
.isNotNull();
assertThat(context.getBean("resourceHandlerMapping", HandlerMapping.class)).isNotNull();
});
}
Expand Down Expand Up @@ -557,6 +562,20 @@ void userConfigurersCanBeOrderedBeforeOrAfterTheAutoConfiguredConfigurer() {
HighPrecedenceConfigurer.class, WebFluxConfig.class, LowPrecedenceConfigurer.class));
}

@Test
void customSameSteConfigurationShouldBeApplied() {
this.contextRunner.withPropertyValues("spring.webflux.session.cookie.same-site:strict").run((context) -> {
MockServerHttpRequest request = MockServerHttpRequest.get("/").build();
MockServerWebExchange exchange = MockServerWebExchange.from(request);
WebSessionManager webSessionManager = context.getBean(WebSessionManager.class);
WebSession webSession = webSessionManager.getSession(exchange).block();
webSession.start();
exchange.getResponse().setComplete().block();
assertThat(exchange.getResponse().getCookies().get("SESSION")).isNotEmpty()
.allMatch((cookie) -> cookie.getSameSite().equals("Strict"));
});
}

private Map<PathPattern, Object> getHandlerMap(ApplicationContext context) {
HandlerMapping mapping = context.getBean("resourceHandlerMapping", HandlerMapping.class);
if (mapping instanceof SimpleUrlHandlerMapping) {
Expand Down

0 comments on commit dc6b5ba

Please sign in to comment.