Create spring-boot-session modules
This commit is contained in:
committed by
Phillip Webb
parent
014240d576
commit
e288c81b7b
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import org.springframework.session.web.http.DefaultCookieSerializer;
|
||||
|
||||
/**
|
||||
* Callback interface that can be implemented by beans wishing to customize the
|
||||
* {@link DefaultCookieSerializer} configuration.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface DefaultCookieSerializerCustomizer {
|
||||
|
||||
/**
|
||||
* Customize the cookie serializer.
|
||||
* @param cookieSerializer the {@code DefaultCookieSerializer} to customize
|
||||
*/
|
||||
void customize(DefaultCookieSerializer cookieSerializer);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2012-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.PropertyMapper;
|
||||
import org.springframework.boot.web.server.Cookie;
|
||||
import org.springframework.boot.web.server.Cookie.SameSite;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.security.web.authentication.RememberMeServices;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.security.web.authentication.SpringSessionRememberMeServices;
|
||||
import org.springframework.session.web.http.CookieHttpSessionIdResolver;
|
||||
import org.springframework.session.web.http.CookieSerializer;
|
||||
import org.springframework.session.web.http.DefaultCookieSerializer;
|
||||
import org.springframework.session.web.http.HttpSessionIdResolver;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Spring Session.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Tommy Ludwig
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
* @author Vedran Pavic
|
||||
* @author Weix Sun
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@ConditionalOnClass(Session.class)
|
||||
@ConditionalOnWebApplication
|
||||
@EnableConfigurationProperties({ ServerProperties.class, SessionProperties.class })
|
||||
public class SessionAutoConfiguration {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnWebApplication(type = Type.SERVLET)
|
||||
@Import(SessionRepositoryFilterConfiguration.class)
|
||||
static class ServletSessionConfiguration {
|
||||
|
||||
@Bean
|
||||
@Conditional(DefaultCookieSerializerCondition.class)
|
||||
DefaultCookieSerializer cookieSerializer(ServerProperties serverProperties,
|
||||
ObjectProvider<DefaultCookieSerializerCustomizer> cookieSerializerCustomizers) {
|
||||
Cookie cookie = serverProperties.getServlet().getSession().getCookie();
|
||||
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
map.from(cookie::getName).to(cookieSerializer::setCookieName);
|
||||
map.from(cookie::getDomain).to(cookieSerializer::setDomainName);
|
||||
map.from(cookie::getPath).to(cookieSerializer::setCookiePath);
|
||||
map.from(cookie::getHttpOnly).to(cookieSerializer::setUseHttpOnlyCookie);
|
||||
map.from(cookie::getSecure).to(cookieSerializer::setUseSecureCookie);
|
||||
map.from(cookie::getMaxAge).asInt(Duration::getSeconds).to(cookieSerializer::setCookieMaxAge);
|
||||
map.from(cookie::getSameSite).as(SameSite::attributeValue).to(cookieSerializer::setSameSite);
|
||||
map.from(cookie::getPartitioned).to(cookieSerializer::setPartitioned);
|
||||
cookieSerializerCustomizers.orderedStream().forEach((customizer) -> customizer.customize(cookieSerializer));
|
||||
return cookieSerializer;
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(RememberMeServices.class)
|
||||
static class RememberMeServicesConfiguration {
|
||||
|
||||
@Bean
|
||||
DefaultCookieSerializerCustomizer rememberMeServicesCookieSerializerCustomizer() {
|
||||
return (cookieSerializer) -> cookieSerializer
|
||||
.setRememberMeRequestAttribute(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Condition to trigger the creation of a {@link DefaultCookieSerializer}. This kicks
|
||||
* in if either no {@link HttpSessionIdResolver} and {@link CookieSerializer} beans
|
||||
* are registered, or if {@link CookieHttpSessionIdResolver} is registered but
|
||||
* {@link CookieSerializer} is not.
|
||||
*/
|
||||
static class DefaultCookieSerializerCondition extends AnyNestedCondition {
|
||||
|
||||
DefaultCookieSerializerCondition() {
|
||||
super(ConfigurationPhase.REGISTER_BEAN);
|
||||
}
|
||||
|
||||
@ConditionalOnMissingBean({ HttpSessionIdResolver.class, CookieSerializer.class })
|
||||
static class NoComponentsAvailable {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnBean(CookieHttpSessionIdResolver.class)
|
||||
@ConditionalOnMissingBean(CookieSerializer.class)
|
||||
static class CookieHttpSessionIdResolverAvailable {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2012-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.convert.DurationUnit;
|
||||
import org.springframework.boot.web.servlet.DispatcherType;
|
||||
import org.springframework.session.web.http.SessionRepositoryFilter;
|
||||
|
||||
/**
|
||||
* Configuration properties for Spring Session.
|
||||
*
|
||||
* @author Tommy Ludwig
|
||||
* @author Stephane Nicoll
|
||||
* @author Vedran Pavic
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@ConfigurationProperties("spring.session")
|
||||
public class SessionProperties {
|
||||
|
||||
/**
|
||||
* Session timeout. If a duration suffix is not specified, seconds will be used.
|
||||
*/
|
||||
@DurationUnit(ChronoUnit.SECONDS)
|
||||
private Duration timeout;
|
||||
|
||||
private Servlet servlet = new Servlet();
|
||||
|
||||
public Duration getTimeout() {
|
||||
return this.timeout;
|
||||
}
|
||||
|
||||
public void setTimeout(Duration timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public Servlet getServlet() {
|
||||
return this.servlet;
|
||||
}
|
||||
|
||||
public void setServlet(Servlet servlet) {
|
||||
this.servlet = servlet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the session timeout. If no timeout is configured, the
|
||||
* {@code fallbackTimeout} is used.
|
||||
* @param fallbackTimeout a fallback timeout value if the timeout isn't configured
|
||||
* @return the session timeout
|
||||
*/
|
||||
public Duration determineTimeout(Supplier<Duration> fallbackTimeout) {
|
||||
return (this.timeout != null) ? this.timeout : fallbackTimeout.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Servlet-related properties.
|
||||
*/
|
||||
public static class Servlet {
|
||||
|
||||
/**
|
||||
* Session repository filter order.
|
||||
*/
|
||||
private int filterOrder = SessionRepositoryFilter.DEFAULT_ORDER;
|
||||
|
||||
/**
|
||||
* Session repository filter dispatcher types.
|
||||
*/
|
||||
private Set<DispatcherType> filterDispatcherTypes = new HashSet<>(
|
||||
Arrays.asList(DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.REQUEST));
|
||||
|
||||
public int getFilterOrder() {
|
||||
return this.filterOrder;
|
||||
}
|
||||
|
||||
public void setFilterOrder(int filterOrder) {
|
||||
this.filterOrder = filterOrder;
|
||||
}
|
||||
|
||||
public Set<DispatcherType> getFilterDispatcherTypes() {
|
||||
return this.filterDispatcherTypes;
|
||||
}
|
||||
|
||||
public void setFilterDispatcherTypes(Set<DispatcherType> filterDispatcherTypes) {
|
||||
this.filterDispatcherTypes = filterDispatcherTypes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.servlet.DispatcherType;
|
||||
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.session.web.http.SessionRepositoryFilter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Configuration for customizing the registration of the {@link SessionRepositoryFilter}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnBean(SessionRepositoryFilter.class)
|
||||
@EnableConfigurationProperties(SessionProperties.class)
|
||||
class SessionRepositoryFilterConfiguration {
|
||||
|
||||
@Bean
|
||||
DelegatingFilterProxyRegistrationBean sessionRepositoryFilterRegistration(SessionProperties sessionProperties,
|
||||
ListableBeanFactory beanFactory) {
|
||||
String[] targetBeanNames = beanFactory.getBeanNamesForType(SessionRepositoryFilter.class, false, false);
|
||||
Assert.state(targetBeanNames.length == 1, "Expected single SessionRepositoryFilter bean");
|
||||
DelegatingFilterProxyRegistrationBean registration = new DelegatingFilterProxyRegistrationBean(
|
||||
targetBeanNames[0]);
|
||||
registration.setDispatcherTypes(getDispatcherTypes(sessionProperties));
|
||||
registration.setOrder(sessionProperties.getServlet().getFilterOrder());
|
||||
return registration;
|
||||
}
|
||||
|
||||
private EnumSet<DispatcherType> getDispatcherTypes(SessionProperties sessionProperties) {
|
||||
SessionProperties.Servlet servletProperties = sessionProperties.getServlet();
|
||||
if (servletProperties.getFilterDispatcherTypes() == null) {
|
||||
return null;
|
||||
}
|
||||
return servletProperties.getFilterDispatcherTypes()
|
||||
.stream()
|
||||
.map((type) -> DispatcherType.valueOf(type.name()))
|
||||
.collect(Collectors.toCollection(() -> EnumSet.noneOf(DispatcherType.class)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Auto-configuration for Spring Session.
|
||||
*/
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"properties": [
|
||||
{
|
||||
"name": "spring.session.servlet.filter-dispatcher-types",
|
||||
"defaultValue": [
|
||||
"async",
|
||||
"error",
|
||||
"request"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
org.springframework.boot.session.autoconfigure.SessionAutoConfiguration
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2012-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.boot.tomcat.autoconfigure.servlet.TomcatServletWebServerAutoConfiguration;
|
||||
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.session.MapSessionRepository;
|
||||
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests to ensure {@link SessionAutoConfiguration} and
|
||||
* {@link SessionRepositoryFilterConfiguration} does not cause early initialization.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class SessionAutoConfigurationEarlyInitializationIntegrationTests {
|
||||
|
||||
@Test
|
||||
void configurationIsFrozenWhenSessionRepositoryAccessed() {
|
||||
new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new)
|
||||
.withSystemProperties("spring.jndi.ignore=true")
|
||||
.withPropertyValues("server.port=0")
|
||||
.withUserConfiguration(TestConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(MapSessionRepository.class));
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableSpringHttpSession
|
||||
@ImportAutoConfiguration({ TomcatServletWebServerAutoConfiguration.class, SessionAutoConfiguration.class })
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
MapSessionRepository mapSessionRepository(ConfigurableApplicationContext context) {
|
||||
Assert.isTrue(context.getBeanFactory().isConfigurationFrozen(), "'context' should be frozen");
|
||||
return new MapSessionRepository(new LinkedHashMap<>());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright 2012-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import jakarta.servlet.DispatcherType;
|
||||
import org.assertj.core.api.InstanceOfAssertFactories;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InOrder;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.boot.web.servlet.AbstractFilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.session.MapSessionRepository;
|
||||
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
|
||||
import org.springframework.session.security.web.authentication.SpringSessionRememberMeServices;
|
||||
import org.springframework.session.web.http.CookieHttpSessionIdResolver;
|
||||
import org.springframework.session.web.http.DefaultCookieSerializer;
|
||||
import org.springframework.session.web.http.HeaderHttpSessionIdResolver;
|
||||
import org.springframework.session.web.http.HttpSessionIdResolver;
|
||||
import org.springframework.session.web.http.SessionRepositoryFilter;
|
||||
import org.springframework.web.filter.DelegatingFilterProxy;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link SessionAutoConfiguration}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
class SessionAutoConfigurationTests {
|
||||
|
||||
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(SessionAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void filterIsRegisteredWithAsyncErrorAndRequestDispatcherTypes() {
|
||||
this.contextRunner.withUserConfiguration(SessionRepositoryConfiguration.class).run((context) -> {
|
||||
AbstractFilterRegistrationBean<?> registration = context.getBean(AbstractFilterRegistrationBean.class);
|
||||
DelegatingFilterProxy delegatingFilterProxy = (DelegatingFilterProxy) registration.getFilter();
|
||||
try {
|
||||
// Trigger actual initialization
|
||||
delegatingFilterProxy.doFilter(null, null, null);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// Ignore
|
||||
}
|
||||
assertThat(delegatingFilterProxy).extracting("delegate")
|
||||
.isSameAs(context.getBean(SessionRepositoryFilter.class));
|
||||
assertThat(registration)
|
||||
.extracting("dispatcherTypes", InstanceOfAssertFactories.iterable(DispatcherType.class))
|
||||
.containsOnly(DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.REQUEST);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void filterOrderCanBeCustomizedWithCustomStore() {
|
||||
this.contextRunner.withUserConfiguration(SessionRepositoryConfiguration.class)
|
||||
.withPropertyValues("spring.session.servlet.filter-order=123")
|
||||
.run((context) -> {
|
||||
AbstractFilterRegistrationBean<?> registration = context.getBean(AbstractFilterRegistrationBean.class);
|
||||
assertThat(registration.getOrder()).isEqualTo(123);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void filterDispatcherTypesCanBeCustomized() {
|
||||
this.contextRunner.withUserConfiguration(SessionRepositoryConfiguration.class)
|
||||
.withPropertyValues("spring.session.servlet.filter-dispatcher-types=error, request")
|
||||
.run((context) -> {
|
||||
AbstractFilterRegistrationBean<?> registration = context.getBean(AbstractFilterRegistrationBean.class);
|
||||
assertThat(registration)
|
||||
.extracting("dispatcherTypes", InstanceOfAssertFactories.iterable(DispatcherType.class))
|
||||
.containsOnly(DispatcherType.ERROR, DispatcherType.REQUEST);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void emptyFilterDispatcherTypesDoNotThrowException() {
|
||||
this.contextRunner.withUserConfiguration(SessionRepositoryConfiguration.class)
|
||||
.withPropertyValues("spring.session.servlet.filter-dispatcher-types=")
|
||||
.run((context) -> {
|
||||
AbstractFilterRegistrationBean<?> registration = context.getBean(AbstractFilterRegistrationBean.class);
|
||||
assertThat(registration)
|
||||
.extracting("dispatcherTypes", InstanceOfAssertFactories.iterable(DispatcherType.class))
|
||||
.isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void sessionCookieConfigurationIsAppliedToAutoConfiguredCookieSerializer() {
|
||||
this.contextRunner.withUserConfiguration(SessionRepositoryConfiguration.class)
|
||||
.withPropertyValues("server.servlet.session.cookie.name=sid", "server.servlet.session.cookie.domain=spring",
|
||||
"server.servlet.session.cookie.path=/test", "server.servlet.session.cookie.httpOnly=false",
|
||||
"server.servlet.session.cookie.secure=false", "server.servlet.session.cookie.maxAge=10s",
|
||||
"server.servlet.session.cookie.sameSite=strict", "server.servlet.session.cookie.partitioned=true")
|
||||
.run((context) -> {
|
||||
DefaultCookieSerializer cookieSerializer = context.getBean(DefaultCookieSerializer.class);
|
||||
assertThat(cookieSerializer).hasFieldOrPropertyWithValue("cookieName", "sid");
|
||||
assertThat(cookieSerializer).hasFieldOrPropertyWithValue("domainName", "spring");
|
||||
assertThat(cookieSerializer).hasFieldOrPropertyWithValue("cookiePath", "/test");
|
||||
assertThat(cookieSerializer).hasFieldOrPropertyWithValue("useHttpOnlyCookie", false);
|
||||
assertThat(cookieSerializer).hasFieldOrPropertyWithValue("useSecureCookie", false);
|
||||
assertThat(cookieSerializer).hasFieldOrPropertyWithValue("cookieMaxAge", 10);
|
||||
assertThat(cookieSerializer).hasFieldOrPropertyWithValue("sameSite", "Strict");
|
||||
assertThat(cookieSerializer).hasFieldOrPropertyWithValue("partitioned", true);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void sessionCookieSameSiteOmittedIsAppliedToAutoConfiguredCookieSerializer() {
|
||||
this.contextRunner.withUserConfiguration(SessionRepositoryConfiguration.class)
|
||||
.withPropertyValues("server.servlet.session.cookie.sameSite=omitted")
|
||||
.run((context) -> {
|
||||
DefaultCookieSerializer cookieSerializer = context.getBean(DefaultCookieSerializer.class);
|
||||
assertThat(cookieSerializer).hasFieldOrPropertyWithValue("sameSite", null);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfiguredCookieSerializerIsUsedBySessionRepositoryFilter() {
|
||||
this.contextRunner.withUserConfiguration(SessionRepositoryConfiguration.class)
|
||||
.withPropertyValues("server.port=0")
|
||||
.run((context) -> {
|
||||
SessionRepositoryFilter<?> filter = context.getBean(SessionRepositoryFilter.class);
|
||||
assertThat(filter).extracting("httpSessionIdResolver.cookieSerializer")
|
||||
.isSameAs(context.getBean(DefaultCookieSerializer.class));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfiguredCookieSerializerBacksOffWhenUserConfiguresACookieSerializer() {
|
||||
this.contextRunner.withUserConfiguration(UserProvidedCookieSerializerConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(DefaultCookieSerializer.class);
|
||||
assertThat(context).hasBean("myCookieSerializer");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void cookiesSerializerIsAutoConfiguredWhenUserConfiguresCookieHttpSessionIdResolver() {
|
||||
this.contextRunner.withUserConfiguration(UserProvidedCookieHttpSessionStrategyConfiguration.class)
|
||||
.run((context) -> assertThat(context.getBeansOfType(DefaultCookieSerializer.class)).isNotEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfiguredCookieSerializerBacksOffWhenUserConfiguresHeaderHttpSessionIdResolver() {
|
||||
this.contextRunner.withUserConfiguration(UserProvidedHeaderHttpSessionStrategyConfiguration.class)
|
||||
.run((context) -> assertThat(context.getBeansOfType(DefaultCookieSerializer.class)).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfiguredCookieSerializerBacksOffWhenUserConfiguresCustomHttpSessionIdResolver() {
|
||||
this.contextRunner.withUserConfiguration(UserProvidedCustomHttpSessionStrategyConfiguration.class)
|
||||
.run((context) -> assertThat(context.getBeansOfType(DefaultCookieSerializer.class)).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfiguredCookieSerializerIsConfiguredWithRememberMeRequestAttribute() {
|
||||
this.contextRunner.withBean(SpringSessionRememberMeServicesConfiguration.class).run((context) -> {
|
||||
DefaultCookieSerializer cookieSerializer = context.getBean(DefaultCookieSerializer.class);
|
||||
assertThat(cookieSerializer).hasFieldOrPropertyWithValue("rememberMeRequestAttribute",
|
||||
SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void cookieSerializerCustomization() {
|
||||
this.contextRunner.withBean(CookieSerializerCustomization.class).run((context) -> {
|
||||
CookieSerializerCustomization customization = context.getBean(CookieSerializerCustomization.class);
|
||||
InOrder inOrder = inOrder(customization.customizer1, customization.customizer2);
|
||||
inOrder.verify(customization.customizer1).customize(any());
|
||||
inOrder.verify(customization.customizer2).customize(any());
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableSpringHttpSession
|
||||
static class SessionRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
MapSessionRepository mySessionRepository() {
|
||||
return new MapSessionRepository(Collections.emptyMap());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableConfigurationProperties(ServerProperties.class)
|
||||
static class ServerPropertiesConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableSpringHttpSession
|
||||
static class UserProvidedCookieSerializerConfiguration extends SessionRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
DefaultCookieSerializer myCookieSerializer() {
|
||||
return new DefaultCookieSerializer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableSpringHttpSession
|
||||
static class UserProvidedCookieHttpSessionStrategyConfiguration extends SessionRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
CookieHttpSessionIdResolver httpSessionStrategy() {
|
||||
return new CookieHttpSessionIdResolver();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableSpringHttpSession
|
||||
static class UserProvidedHeaderHttpSessionStrategyConfiguration extends SessionRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
HeaderHttpSessionIdResolver httpSessionStrategy() {
|
||||
return HeaderHttpSessionIdResolver.xAuthToken();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableSpringHttpSession
|
||||
static class UserProvidedCustomHttpSessionStrategyConfiguration extends SessionRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
HttpSessionIdResolver httpSessionStrategy() {
|
||||
return mock(HttpSessionIdResolver.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableSpringHttpSession
|
||||
static class SpringSessionRememberMeServicesConfiguration extends SessionRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
SpringSessionRememberMeServices rememberMeServices() {
|
||||
return new SpringSessionRememberMeServices();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableSpringHttpSession
|
||||
static class CookieSerializerCustomization extends SessionRepositoryConfiguration {
|
||||
|
||||
private final DefaultCookieSerializerCustomizer customizer1 = mock(DefaultCookieSerializerCustomizer.class);
|
||||
|
||||
private final DefaultCookieSerializerCustomizer customizer2 = mock(DefaultCookieSerializerCustomizer.class);
|
||||
|
||||
@Bean
|
||||
@Order(1)
|
||||
DefaultCookieSerializerCustomizer customizer1() {
|
||||
return this.customizer1;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(2)
|
||||
DefaultCookieSerializerCustomizer customizer2() {
|
||||
return this.customizer2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.session.MapSessionRepository;
|
||||
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
|
||||
import org.springframework.session.web.http.DefaultCookieSerializer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link SessionAutoConfiguration} when Spring Security is not on the
|
||||
* classpath.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@ClassPathExclusions("spring-security-*")
|
||||
class SessionAutoConfigurationWithoutSecurityTests {
|
||||
|
||||
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(SessionAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void sessionCookieConfigurationIsAppliedToAutoConfiguredCookieSerializer() {
|
||||
this.contextRunner.withUserConfiguration(SessionRepositoryConfiguration.class).run((context) -> {
|
||||
DefaultCookieSerializer cookieSerializer = context.getBean(DefaultCookieSerializer.class);
|
||||
assertThat(cookieSerializer).hasFieldOrPropertyWithValue("rememberMeRequestAttribute", null);
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableSpringHttpSession
|
||||
static class SessionRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
MapSessionRepository mySessionRepository() {
|
||||
return new MapSessionRepository(Collections.emptyMap());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link SessionProperties}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class SessionPropertiesTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void determineTimeoutWithTimeoutIgnoreFallback() {
|
||||
SessionProperties properties = new SessionProperties();
|
||||
properties.setTimeout(Duration.ofMinutes(1));
|
||||
Supplier<Duration> fallback = mock(Supplier.class);
|
||||
assertThat(properties.determineTimeout(fallback)).isEqualTo(Duration.ofMinutes(1));
|
||||
then(fallback).shouldHaveNoInteractions();
|
||||
}
|
||||
|
||||
@Test
|
||||
void determineTimeoutWithNoTimeoutUseFallback() {
|
||||
SessionProperties properties = new SessionProperties();
|
||||
properties.setTimeout(null);
|
||||
Duration fallback = Duration.ofMinutes(2);
|
||||
assertThat(properties.determineTimeout(() -> fallback)).isSameAs(fallback);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2012-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ContextConsumer;
|
||||
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
|
||||
import org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext;
|
||||
import org.springframework.boot.web.server.reactive.MockReactiveWebServerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.mock.web.server.MockServerWebExchange;
|
||||
import org.springframework.session.ReactiveMapSessionRepository;
|
||||
import org.springframework.session.ReactiveSessionRepository;
|
||||
import org.springframework.session.config.annotation.web.server.EnableSpringWebSession;
|
||||
import org.springframework.web.server.WebSession;
|
||||
import org.springframework.web.server.session.WebSessionManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Base class for Spring Session auto-configuration tests when the backing store is
|
||||
* reactive.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public abstract class AbstractReactiveSessionAutoConfigurationTests {
|
||||
|
||||
private static final MockReactiveWebServerFactory mockReactiveWebServerFactory = new MockReactiveWebServerFactory();
|
||||
|
||||
protected ReactiveWebApplicationContextRunner contextRunner;
|
||||
|
||||
@Test
|
||||
void backOffIfReactiveSessionRepositoryIsPresent() {
|
||||
this.contextRunner.withUserConfiguration(ReactiveSessionRepositoryConfiguration.class).run((context) -> {
|
||||
ReactiveMapSessionRepository repository = validateSessionRepository(context,
|
||||
ReactiveMapSessionRepository.class);
|
||||
assertThat(context).getBean("mySessionRepository").isSameAs(repository);
|
||||
});
|
||||
}
|
||||
|
||||
protected ContextConsumer<ReactiveWebApplicationContext> assertExchangeWithSession(
|
||||
Consumer<MockServerWebExchange> exchange) {
|
||||
return (context) -> {
|
||||
MockServerHttpRequest request = MockServerHttpRequest.get("/").build();
|
||||
MockServerWebExchange webExchange = MockServerWebExchange.from(request);
|
||||
WebSessionManager webSessionManager = context.getBean(WebSessionManager.class);
|
||||
WebSession webSession = webSessionManager.getSession(webExchange).block();
|
||||
webSession.start();
|
||||
webExchange.getResponse().setComplete().block();
|
||||
exchange.accept(webExchange);
|
||||
};
|
||||
}
|
||||
|
||||
protected <T extends ReactiveSessionRepository<?>> T validateSessionRepository(
|
||||
AssertableReactiveWebApplicationContext context, Class<T> type) {
|
||||
assertThat(context).hasSingleBean(WebSessionManager.class);
|
||||
assertThat(context).hasSingleBean(ReactiveSessionRepository.class);
|
||||
ReactiveSessionRepository<?> repository = context.getBean(ReactiveSessionRepository.class);
|
||||
assertThat(repository).as("Wrong session repository type").isInstanceOf(type);
|
||||
return type.cast(repository);
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
protected static class ReactiveWebServerConfiguration {
|
||||
|
||||
@Bean
|
||||
MockReactiveWebServerFactory mockReactiveWebServerFactory() {
|
||||
return mockReactiveWebServerFactory;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableSpringWebSession
|
||||
static class ReactiveSessionRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
ReactiveMapSessionRepository mySessionRepository() {
|
||||
return new ReactiveMapSessionRepository(Collections.emptyMap());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2012-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.session.autoconfigure;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.session.MapSessionRepository;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
|
||||
import org.springframework.session.web.http.SessionRepositoryFilter;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Base class for Spring Session auto-configuration tests when the backing store cannot be
|
||||
* reactive.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Weix Sun
|
||||
* @see AbstractReactiveSessionAutoConfigurationTests
|
||||
*/
|
||||
public abstract class AbstractSessionAutoConfigurationTests {
|
||||
|
||||
protected WebApplicationContextRunner contextRunner;
|
||||
|
||||
@Test
|
||||
void backOffIfSessionRepositoryIsPresent() {
|
||||
this.contextRunner.withUserConfiguration(SessionRepositoryConfiguration.class).run((context) -> {
|
||||
MapSessionRepository repository = validateSessionRepository(context, MapSessionRepository.class);
|
||||
assertThat(context).getBean("mySessionRepository").isSameAs(repository);
|
||||
});
|
||||
}
|
||||
|
||||
protected <T extends SessionRepository<?>> T validateSessionRepository(AssertableWebApplicationContext context,
|
||||
Class<T> type) {
|
||||
assertThat(context).hasSingleBean(SessionRepositoryFilter.class);
|
||||
assertThat(context).hasSingleBean(SessionRepository.class);
|
||||
SessionRepository<?> repository = context.getBean(SessionRepository.class);
|
||||
assertThat(repository).as("Wrong session repository type").isInstanceOf(type);
|
||||
return type.cast(repository);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableSpringHttpSession
|
||||
static class SessionRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
MapSessionRepository mySessionRepository() {
|
||||
return new MapSessionRepository(Collections.emptyMap());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user