From 02e836b7a740551856e19964a77691a3770c310d Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 25 Jul 2017 09:25:34 +0100 Subject: [PATCH] Allow Session's repository filter to be configured via the environment Closes gh-8301 --- .../session/SessionProperties.java | 49 +++++++++++++++++++ .../SessionRepositoryFilterConfiguration.java | 25 ++++++++-- .../SessionAutoConfigurationTests.java | 21 ++++++++ .../appendix-application-properties.adoc | 2 + 4 files changed, 93 insertions(+), 4 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionProperties.java index f647ecfb65..70bd816988 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionProperties.java @@ -16,9 +16,14 @@ package org.springframework.boot.autoconfigure.session; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.session.web.http.SessionRepositoryFilter; /** * Configuration properties for Spring Session. @@ -38,6 +43,8 @@ public class SessionProperties { private Integer timeout; + private Servlet servlet = new Servlet(); + public SessionProperties(ObjectProvider serverProperties) { ServerProperties properties = serverProperties.getIfUnique(); this.timeout = (properties != null ? properties.getSession().getTimeout() : null); @@ -60,4 +67,46 @@ public class SessionProperties { return this.timeout; } + public Servlet getServlet() { + return this.servlet; + } + + public void setServlet(Servlet servlet) { + this.servlet = servlet; + } + + /** + * Servlet-related properties. + */ + public static class Servlet { + + /** + * Session repository filter order. + */ + private int filterOrder = SessionRepositoryFilter.DEFAULT_ORDER; + + /** + * Session repository filter dispatcher types. + */ + private Set filterDispatcherTypes = new HashSet<>( + Arrays.asList("ASYNC", "ERROR", "REQUEST")); + + public int getFilterOrder() { + return this.filterOrder; + } + + public void setFilterOrder(int filterOrder) { + this.filterOrder = filterOrder; + } + + public Set getFilterDispatcherTypes() { + return this.filterDispatcherTypes; + } + + public void setFilterDispatcherTypes(Set filterDispatcherTypes) { + this.filterDispatcherTypes = filterDispatcherTypes; + } + + } + } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionRepositoryFilterConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionRepositoryFilterConfiguration.java index 286226fae5..9f6ee6026f 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionRepositoryFilterConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/SessionRepositoryFilterConfiguration.java @@ -17,10 +17,14 @@ package org.springframework.boot.autoconfigure.session; import java.util.EnumSet; +import java.util.Locale; +import java.util.Set; +import java.util.stream.Collectors; import javax.servlet.DispatcherType; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -33,17 +37,30 @@ import org.springframework.session.web.http.SessionRepositoryFilter; */ @Configuration @ConditionalOnBean(SessionRepositoryFilter.class) +@EnableConfigurationProperties(SessionProperties.class) class SessionRepositoryFilterConfiguration { @Bean public FilterRegistrationBean> sessionRepositoryFilterRegistration( - SessionRepositoryFilter filter) { + SessionProperties sessionProperties, SessionRepositoryFilter filter) { FilterRegistrationBean> registration = new FilterRegistrationBean<>( filter); - registration.setDispatcherTypes(EnumSet.of(DispatcherType.ASYNC, - DispatcherType.ERROR, DispatcherType.REQUEST)); - registration.setOrder(SessionRepositoryFilter.DEFAULT_ORDER); + registration.setDispatcherTypes(getDispatcherTypes(sessionProperties)); + registration.setOrder(sessionProperties.getServlet().getFilterOrder()); return registration; } + private EnumSet getDispatcherTypes( + SessionProperties sessionProperties) { + Set filterDispatcherTypes = sessionProperties.getServlet() + .getFilterDispatcherTypes(); + if (filterDispatcherTypes == null) { + return null; + } + return filterDispatcherTypes.stream() + .map((type) -> type.toUpperCase(Locale.ENGLISH)) + .map(DispatcherType::valueOf).collect(Collectors + .collectingAndThen(Collectors.toSet(), EnumSet::copyOf)); + } + } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationTests.java index 90eabbccac..30963fdaaa 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationTests.java @@ -116,6 +116,27 @@ public class SessionAutoConfigurationTests extends AbstractSessionAutoConfigurat DispatcherType.ERROR, DispatcherType.REQUEST); } + @Test + public void filterOrderCanBeCustomized() { + load("spring.session.store-type=hash-map", + "spring.session.servlet.filter-order=123"); + FilterRegistrationBean registration = this.context + .getBean(FilterRegistrationBean.class); + assertThat(registration.getOrder()).isEqualTo(123); + } + + @SuppressWarnings("unchecked") + @Test + public void filterDispatcherTypesCanBeCustomized() { + load("spring.session.store-type=hash-map", + "spring.session.servlet.filter-dispatcher-types=error, request"); + FilterRegistrationBean registration = this.context + .getBean(FilterRegistrationBean.class); + assertThat((EnumSet) ReflectionTestUtils.getField(registration, + "dispatcherTypes")).containsOnly(DispatcherType.ERROR, + DispatcherType.REQUEST); + } + @Configuration static class SessionRepositoryConfiguration { diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index f638764568..09241475c5 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -193,6 +193,8 @@ content into your application; rather pick only the properties that you need. server.session.cookie.path= # Path of the session cookie. server.session.cookie.secure= # "Secure" flag for the session cookie. server.session.persistent=false # Persist session data between restarts. + server.session.servlet.filter-order=-2147483598 # Session repository filter order. + server.session.servlet.filter-dispatcher-types=ASYNC, ERROR, REQUEST # Session repository filter dispatcher types. server.session.store-dir= # Directory used to store session data. server.session.timeout= # Session timeout in seconds. server.session.tracking-modes= # Session tracking modes (one or more of the following: "cookie", "url", "ssl").