Skip to content

Commit efa0436

Browse files
committed
Merge pull request #26714 from weixsun
* gh-26714: Relocate and unify reactive cookie properties Polish 'Add more session properties for reactive web servers' Add more session properties for reactive web servers Closes gh-26714
2 parents 3729c49 + b72ff25 commit efa0436

File tree

16 files changed

+591
-153
lines changed

16 files changed

+591
-153
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoReactiveSessionConfiguration.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
2222
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2323
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2424
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
25+
import org.springframework.boot.autoconfigure.web.ServerProperties;
2526
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2627
import org.springframework.context.annotation.Conditional;
2728
import org.springframework.context.annotation.Configuration;
@@ -34,6 +35,7 @@
3435
* Mongo-backed reactive session configuration.
3536
*
3637
* @author Andy Wilkinson
38+
* @author Weix Sun
3739
*/
3840
@Configuration(proxyBeanMethods = false)
3941
@ConditionalOnClass({ ReactiveMongoOperations.class, ReactiveMongoSessionRepository.class })
@@ -47,8 +49,10 @@ class MongoReactiveSessionConfiguration {
4749
static class SpringBootReactiveMongoWebSessionConfiguration extends ReactiveMongoWebSessionConfiguration {
4850

4951
@Autowired
50-
void customize(SessionProperties sessionProperties, MongoSessionProperties mongoSessionProperties) {
51-
Duration timeout = sessionProperties.getTimeout();
52+
void customize(SessionProperties sessionProperties, MongoSessionProperties mongoSessionProperties,
53+
ServerProperties serverProperties) {
54+
Duration timeout = sessionProperties
55+
.determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout());
5256
if (timeout != null) {
5357
setMaxInactiveIntervalInSeconds((int) timeout.getSeconds());
5458
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisReactiveSessionConfiguration.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
2222
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2323
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2424
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
25+
import org.springframework.boot.autoconfigure.web.ServerProperties;
2526
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2627
import org.springframework.context.annotation.Conditional;
2728
import org.springframework.context.annotation.Configuration;
@@ -34,6 +35,7 @@
3435
* Redis-backed reactive session configuration.
3536
*
3637
* @author Andy Wilkinson
38+
* @author Weix Sun
3739
*/
3840
@Configuration(proxyBeanMethods = false)
3941
@ConditionalOnClass({ ReactiveRedisConnectionFactory.class, ReactiveRedisSessionRepository.class })
@@ -47,8 +49,10 @@ class RedisReactiveSessionConfiguration {
4749
static class SpringBootRedisWebSessionConfiguration extends RedisWebSessionConfiguration {
4850

4951
@Autowired
50-
void customize(SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties) {
51-
Duration timeout = sessionProperties.getTimeout();
52+
void customize(SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties,
53+
ServerProperties serverProperties) {
54+
Duration timeout = sessionProperties
55+
.determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout());
5256
if (timeout != null) {
5357
setMaxInactiveIntervalInSeconds((int) timeout.getSeconds());
5458
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionAutoConfiguration.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.boot.autoconfigure.session;
1818

19+
import java.time.Duration;
1920
import java.util.ArrayList;
2021
import java.util.Arrays;
2122
import java.util.List;
@@ -43,6 +44,8 @@
4344
import org.springframework.boot.autoconfigure.web.ServerProperties;
4445
import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration;
4546
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
47+
import org.springframework.boot.autoconfigure.web.reactive.WebFluxProperties;
48+
import org.springframework.boot.autoconfigure.web.reactive.WebSessionIdResolverAutoConfiguration;
4649
import org.springframework.boot.context.properties.EnableConfigurationProperties;
4750
import org.springframework.boot.context.properties.PropertyMapper;
4851
import org.springframework.boot.web.servlet.server.Session.Cookie;
@@ -71,15 +74,17 @@
7174
* @author Eddú Meléndez
7275
* @author Stephane Nicoll
7376
* @author Vedran Pavic
77+
* @author Weix Sun
7478
* @since 1.4.0
7579
*/
7680
@Configuration(proxyBeanMethods = false)
7781
@ConditionalOnClass(Session.class)
7882
@ConditionalOnWebApplication
79-
@EnableConfigurationProperties({ ServerProperties.class, SessionProperties.class })
83+
@EnableConfigurationProperties({ ServerProperties.class, SessionProperties.class, WebFluxProperties.class })
8084
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HazelcastAutoConfiguration.class,
8185
JdbcTemplateAutoConfiguration.class, MongoDataAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class,
82-
RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class })
86+
RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class,
87+
WebSessionIdResolverAutoConfiguration.class })
8388
@AutoConfigureBefore({ HttpHandlerAutoConfiguration.class, WebFluxAutoConfiguration.class })
8489
public class SessionAutoConfiguration {
8590

@@ -100,7 +105,7 @@ DefaultCookieSerializer cookieSerializer(ServerProperties serverProperties,
100105
map.from(cookie::getPath).to(cookieSerializer::setCookiePath);
101106
map.from(cookie::getHttpOnly).to(cookieSerializer::setUseHttpOnlyCookie);
102107
map.from(cookie::getSecure).to(cookieSerializer::setUseSecureCookie);
103-
map.from(cookie::getMaxAge).to((maxAge) -> cookieSerializer.setCookieMaxAge((int) maxAge.getSeconds()));
108+
map.from(cookie::getMaxAge).asInt(Duration::getSeconds).to(cookieSerializer::setCookieMaxAge);
104109
cookieSerializerCustomizers.orderedStream().forEach((customizer) -> customizer.customize(cookieSerializer));
105110
return cookieSerializer;
106111
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.boot.context.properties.NestedConfigurationProperty;
3535
import org.springframework.boot.convert.DurationUnit;
3636
import org.springframework.boot.web.server.Compression;
37+
import org.springframework.boot.web.server.Cookie;
3738
import org.springframework.boot.web.server.Http2;
3839
import org.springframework.boot.web.server.Shutdown;
3940
import org.springframework.boot.web.server.Ssl;
@@ -116,6 +117,8 @@ public class ServerProperties {
116117

117118
private final Servlet servlet = new Servlet();
118119

120+
private final Reactive reactive = new Reactive();
121+
119122
private final Tomcat tomcat = new Tomcat();
120123

121124
private final Jetty jetty = new Jetty();
@@ -188,6 +191,10 @@ public Servlet getServlet() {
188191
return this.servlet;
189192
}
190193

194+
public Reactive getReactive() {
195+
return this.reactive;
196+
}
197+
191198
public Tomcat getTomcat() {
192199
return this.tomcat;
193200
}
@@ -213,7 +220,7 @@ public void setForwardHeadersStrategy(ForwardHeadersStrategy forwardHeadersStrat
213220
}
214221

215222
/**
216-
* Servlet properties.
223+
* Servlet server properties.
217224
*/
218225
public static class Servlet {
219226

@@ -296,6 +303,44 @@ public Session getSession() {
296303

297304
}
298305

306+
/**
307+
* Reactive server properties.
308+
*/
309+
public static class Reactive {
310+
311+
private final Session session = new Session();
312+
313+
public Session getSession() {
314+
return this.session;
315+
}
316+
317+
public static class Session {
318+
319+
/**
320+
* Session timeout. If a duration suffix is not specified, seconds will be
321+
* used.
322+
*/
323+
@DurationUnit(ChronoUnit.SECONDS)
324+
private Duration timeout = Duration.ofMinutes(30);
325+
326+
private final Cookie cookie = new Cookie();
327+
328+
public Duration getTimeout() {
329+
return this.timeout;
330+
}
331+
332+
public void setTimeout(Duration timeout) {
333+
this.timeout = timeout;
334+
}
335+
336+
public Cookie getCookie() {
337+
return this.cookie;
338+
}
339+
340+
}
341+
342+
}
343+
299344
/**
300345
* Tomcat properties.
301346
*/

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
package org.springframework.boot.autoconfigure.web.reactive;
1818

1919
import java.time.Duration;
20-
import java.util.function.Supplier;
2120

2221
import org.apache.commons.logging.Log;
2322
import org.apache.commons.logging.LogFactory;
23+
import reactor.core.publisher.Mono;
2424

2525
import org.springframework.beans.factory.ListableBeanFactory;
2626
import org.springframework.beans.factory.ObjectProvider;
@@ -36,6 +36,7 @@
3636
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
3737
import org.springframework.boot.autoconfigure.validation.ValidatorAdapter;
3838
import org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain;
39+
import org.springframework.boot.autoconfigure.web.ServerProperties;
3940
import org.springframework.boot.autoconfigure.web.WebProperties;
4041
import org.springframework.boot.autoconfigure.web.WebProperties.Resources;
4142
import org.springframework.boot.autoconfigure.web.format.DateTimeFormatters;
@@ -72,12 +73,13 @@
7273
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
7374
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
7475
import org.springframework.web.reactive.result.view.ViewResolver;
76+
import org.springframework.web.server.WebSession;
7577
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
7678
import org.springframework.web.server.i18n.AcceptHeaderLocaleContextResolver;
7779
import org.springframework.web.server.i18n.FixedLocaleContextResolver;
7880
import org.springframework.web.server.i18n.LocaleContextResolver;
79-
import org.springframework.web.server.session.CookieWebSessionIdResolver;
8081
import org.springframework.web.server.session.DefaultWebSessionManager;
82+
import org.springframework.web.server.session.InMemoryWebSessionStore;
8183
import org.springframework.web.server.session.WebSessionIdResolver;
8284
import org.springframework.web.server.session.WebSessionManager;
8385

@@ -92,14 +94,16 @@
9294
* @author Eddú Meléndez
9395
* @author Artsiom Yudovin
9496
* @author Chris Bono
97+
* @author Weix Sun
9598
* @since 2.0.0
9699
*/
97100
@Configuration(proxyBeanMethods = false)
98101
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
99102
@ConditionalOnClass(WebFluxConfigurer.class)
100103
@ConditionalOnMissingBean({ WebFluxConfigurationSupport.class })
101104
@AutoConfigureAfter({ ReactiveWebServerFactoryAutoConfiguration.class, CodecsAutoConfiguration.class,
102-
ReactiveMultipartAutoConfiguration.class, ValidationAutoConfiguration.class })
105+
ReactiveMultipartAutoConfiguration.class, ValidationAutoConfiguration.class,
106+
WebSessionIdResolverAutoConfiguration.class })
103107
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
104108
public class WebFluxAutoConfiguration {
105109

@@ -231,19 +235,22 @@ private void customizeResourceHandlerRegistration(ResourceHandlerRegistration re
231235
* Configuration equivalent to {@code @EnableWebFlux}.
232236
*/
233237
@Configuration(proxyBeanMethods = false)
234-
@EnableConfigurationProperties(WebProperties.class)
238+
@EnableConfigurationProperties({ WebProperties.class, ServerProperties.class })
235239
public static class EnableWebFluxConfiguration extends DelegatingWebFluxConfiguration {
236240

237241
private final WebFluxProperties webFluxProperties;
238242

239243
private final WebProperties webProperties;
240244

245+
private final ServerProperties serverProperties;
246+
241247
private final WebFluxRegistrations webFluxRegistrations;
242248

243249
public EnableWebFluxConfiguration(WebFluxProperties webFluxProperties, WebProperties webProperties,
244-
ObjectProvider<WebFluxRegistrations> webFluxRegistrations) {
250+
ServerProperties serverProperties, ObjectProvider<WebFluxRegistrations> webFluxRegistrations) {
245251
this.webFluxProperties = webFluxProperties;
246252
this.webProperties = webProperties;
253+
this.serverProperties = serverProperties;
247254
this.webFluxRegistrations = webFluxRegistrations.getIfUnique();
248255
}
249256

@@ -304,19 +311,12 @@ public LocaleContextResolver localeContextResolver() {
304311
@ConditionalOnMissingBean(name = WebHttpHandlerBuilder.WEB_SESSION_MANAGER_BEAN_NAME)
305312
public WebSessionManager webSessionManager(ObjectProvider<WebSessionIdResolver> webSessionIdResolver) {
306313
DefaultWebSessionManager webSessionManager = new DefaultWebSessionManager();
307-
webSessionManager.setSessionIdResolver(webSessionIdResolver.getIfAvailable(cookieWebSessionIdResolver()));
314+
Duration timeout = this.serverProperties.getReactive().getSession().getTimeout();
315+
webSessionManager.setSessionStore(new MaxIdleTimeInMemoryWebSessionStore(timeout));
316+
webSessionIdResolver.ifAvailable(webSessionManager::setSessionIdResolver);
308317
return webSessionManager;
309318
}
310319

311-
private Supplier<WebSessionIdResolver> cookieWebSessionIdResolver() {
312-
return () -> {
313-
CookieWebSessionIdResolver webSessionIdResolver = new CookieWebSessionIdResolver();
314-
webSessionIdResolver.addCookieInitializer((cookie) -> cookie
315-
.sameSite(this.webFluxProperties.getSession().getCookie().getSameSite().attribute()));
316-
return webSessionIdResolver;
317-
};
318-
}
319-
320320
}
321321

322322
@Configuration(proxyBeanMethods = false)
@@ -331,4 +331,23 @@ ResourceChainResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCu
331331

332332
}
333333

334+
static final class MaxIdleTimeInMemoryWebSessionStore extends InMemoryWebSessionStore {
335+
336+
private final Duration timeout;
337+
338+
private MaxIdleTimeInMemoryWebSessionStore(Duration timeout) {
339+
this.timeout = timeout;
340+
}
341+
342+
@Override
343+
public Mono<WebSession> createWebSession() {
344+
return super.createWebSession().doOnSuccess(this::setMaxIdleTime);
345+
}
346+
347+
private void setMaxIdleTime(WebSession session) {
348+
session.setMaxIdleTime(this.timeout);
349+
}
350+
351+
}
352+
334353
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxProperties.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.boot.autoconfigure.web.reactive;
1818

1919
import org.springframework.boot.context.properties.ConfigurationProperties;
20+
import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
2021
import org.springframework.util.StringUtils;
2122

2223
/**
@@ -67,6 +68,7 @@ public Format getFormat() {
6768
return this.format;
6869
}
6970

71+
@DeprecatedConfigurationProperty(replacement = "server.reactive.session")
7072
public Session getSession() {
7173
return this.session;
7274
}
@@ -122,23 +124,39 @@ public void setDateTime(String dateTime) {
122124

123125
}
124126

127+
/**
128+
* Session properties.
129+
*
130+
* @deprecated since 2.6.0 for removal in 2.8.0 in favor of
131+
* {@code server.reactive.session}.
132+
*/
133+
@Deprecated
125134
public static class Session {
126135

127136
private final Cookie cookie = new Cookie();
128137

138+
@DeprecatedConfigurationProperty(replacement = "server.reactive.session.cookie")
129139
public Cookie getCookie() {
130140
return this.cookie;
131141
}
132142

133143
}
134144

145+
/**
146+
* Session cookie properties.
147+
*
148+
* @deprecated since 2.6.0 for removal in 2.8.0 in favor of
149+
* {@link org.springframework.boot.web.server.Cookie}.
150+
*/
151+
@Deprecated
135152
public static class Cookie {
136153

137154
/**
138155
* SameSite attribute value for session Cookies.
139156
*/
140-
private SameSite sameSite = SameSite.LAX;
157+
private SameSite sameSite;
141158

159+
@DeprecatedConfigurationProperty(replacement = "server.reactive.session.cookie.same-site")
142160
public SameSite getSameSite() {
143161
return this.sameSite;
144162
}
@@ -149,6 +167,12 @@ public void setSameSite(SameSite sameSite) {
149167

150168
}
151169

170+
/**
171+
* SameSite values.
172+
* @deprecated since 2.6.0 for removal in 2.8.0 in favor of
173+
* {@link org.springframework.boot.web.server.Cookie.SameSite}.
174+
*/
175+
@Deprecated
152176
public enum SameSite {
153177

154178
/**

0 commit comments

Comments
 (0)