Skip to content

Commit 32454b8

Browse files
vpavicwilkinsona
authored andcommitted
Add support for customizing Spring Session's cookie serializer
This commit introduces a CookieSerializerCustomizer callback that allows the customization of the auto-configured DefaultCookieSerializer bean. This is particularly useful for configuring cookie serializer's capabilities, such as SameSite, that are not supported by the Servlet API and therefore not exposed via server.servlet.session.cookie.* properties. See gh-20961
1 parent f3d717e commit 32454b8

File tree

2 files changed

+55
-9
lines changed

2 files changed

+55
-9
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2012-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.session;
18+
19+
import org.springframework.session.web.http.DefaultCookieSerializer;
20+
21+
/**
22+
* Callback interface that can be implemented by beans wishing to customize the
23+
* {@link DefaultCookieSerializer} configuration.
24+
*
25+
* @author Vedran Pavic
26+
* @since 2.3.0
27+
*/
28+
@FunctionalInterface
29+
public interface CookieSerializerCustomizer {
30+
31+
/**
32+
* Customize the cookie serializer.
33+
* @param cookieSerializer the {@code CookieSerializer} to customize
34+
*/
35+
void customize(DefaultCookieSerializer cookieSerializer);
36+
37+
}

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

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import org.springframework.context.annotation.Import;
5454
import org.springframework.context.annotation.ImportSelector;
5555
import org.springframework.core.type.AnnotationMetadata;
56+
import org.springframework.security.web.authentication.RememberMeServices;
5657
import org.springframework.session.ReactiveSessionRepository;
5758
import org.springframework.session.Session;
5859
import org.springframework.session.SessionRepository;
@@ -61,7 +62,6 @@
6162
import org.springframework.session.web.http.CookieSerializer;
6263
import org.springframework.session.web.http.DefaultCookieSerializer;
6364
import org.springframework.session.web.http.HttpSessionIdResolver;
64-
import org.springframework.util.ClassUtils;
6565

6666
/**
6767
* {@link EnableAutoConfiguration Auto-configuration} for Spring Session.
@@ -83,16 +83,15 @@
8383
@AutoConfigureBefore(HttpHandlerAutoConfiguration.class)
8484
public class SessionAutoConfiguration {
8585

86-
private static final String REMEMBER_ME_SERVICES_CLASS = "org.springframework.security.web.authentication.RememberMeServices";
87-
8886
@Configuration(proxyBeanMethods = false)
8987
@ConditionalOnWebApplication(type = Type.SERVLET)
9088
@Import({ ServletSessionRepositoryValidator.class, SessionRepositoryFilterConfiguration.class })
9189
static class ServletSessionConfiguration {
9290

9391
@Bean
9492
@Conditional(DefaultCookieSerializerCondition.class)
95-
DefaultCookieSerializer cookieSerializer(ServerProperties serverProperties) {
93+
DefaultCookieSerializer cookieSerializer(ServerProperties serverProperties,
94+
ObjectProvider<CookieSerializerCustomizer> cookieSerializerCustomizers) {
9695
Cookie cookie = serverProperties.getServlet().getSession().getCookie();
9796
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
9897
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
@@ -102,12 +101,21 @@ DefaultCookieSerializer cookieSerializer(ServerProperties serverProperties) {
102101
map.from(cookie::getHttpOnly).to(cookieSerializer::setUseHttpOnlyCookie);
103102
map.from(cookie::getSecure).to(cookieSerializer::setUseSecureCookie);
104103
map.from(cookie::getMaxAge).to((maxAge) -> cookieSerializer.setCookieMaxAge((int) maxAge.getSeconds()));
105-
if (ClassUtils.isPresent(REMEMBER_ME_SERVICES_CLASS, getClass().getClassLoader())) {
106-
new RememberMeServicesCookieSerializerCustomizer().apply(cookieSerializer);
107-
}
104+
cookieSerializerCustomizers.orderedStream().forEach((customizer) -> customizer.customize(cookieSerializer));
108105
return cookieSerializer;
109106
}
110107

108+
@Configuration(proxyBeanMethods = false)
109+
@ConditionalOnClass(RememberMeServices.class)
110+
static class RememberMeServicesConfiguration {
111+
112+
@Bean
113+
RememberMeServicesCookieSerializerCustomizer rememberMeServicesCookieSerializerCustomizer() {
114+
return new RememberMeServicesCookieSerializerCustomizer();
115+
}
116+
117+
}
118+
111119
@Configuration(proxyBeanMethods = false)
112120
@ConditionalOnMissingBean(SessionRepository.class)
113121
@Import({ ServletSessionRepositoryImplementationValidator.class,
@@ -137,9 +145,10 @@ static class ReactiveSessionRepositoryConfiguration {
137145
* Customization for {@link SpringSessionRememberMeServices} that is only instantiated
138146
* when Spring Security is on the classpath.
139147
*/
140-
static class RememberMeServicesCookieSerializerCustomizer {
148+
static class RememberMeServicesCookieSerializerCustomizer implements CookieSerializerCustomizer {
141149

142-
void apply(DefaultCookieSerializer cookieSerializer) {
150+
@Override
151+
public void customize(DefaultCookieSerializer cookieSerializer) {
143152
cookieSerializer.setRememberMeRequestAttribute(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR);
144153
}
145154

0 commit comments

Comments
 (0)