Add session configuration properties
Add support for the following server properties which can be used to configure the session: server.session.tracking-modes server.session.cookie.name server.session.cookie.domain server.session.cookie.path server.session.cookie.comment server.session.cookie.http-only server.session.cookie.secure server.session.cookie.max-age In addition `server.session-timeout` is now deprecated and has been replaced with `server.session.timeout`. Fixes gh-3240
This commit is contained in:
parent
5938c967a3
commit
3588ca8637
|
@ -61,10 +61,9 @@ public class SessionAutoConfiguration {
|
|||
|
||||
@PostConstruct
|
||||
public void applyConfigurationProperties() {
|
||||
if (this.serverProperties.getSessionTimeout() != null) {
|
||||
this.sessionRepository
|
||||
.setDefaultMaxInactiveInterval(this.serverProperties
|
||||
.getSessionTimeout());
|
||||
Integer timeout = this.serverProperties.getSession().getTimeout();
|
||||
if (timeout != null) {
|
||||
this.sessionRepository.setDefaultMaxInactiveInterval(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,12 @@ import java.net.InetAddress;
|
|||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.SessionCookieConfig;
|
||||
import javax.servlet.SessionTrackingMode;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.apache.catalina.Context;
|
||||
|
@ -31,6 +36,7 @@ import org.apache.catalina.valves.RemoteIpValve;
|
|||
import org.apache.coyote.AbstractProtocol;
|
||||
import org.apache.coyote.ProtocolHandler;
|
||||
import org.apache.coyote.http11.AbstractHttp11Protocol;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties.Session.Cookie;
|
||||
import org.springframework.boot.context.embedded.Compression;
|
||||
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
|
@ -38,6 +44,7 @@ import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomi
|
|||
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.InitParameterConfiguringServletContextInitializer;
|
||||
import org.springframework.boot.context.embedded.JspServlet;
|
||||
import org.springframework.boot.context.embedded.ServletContextInitializer;
|
||||
import org.springframework.boot.context.embedded.Ssl;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
|
||||
|
@ -72,11 +79,6 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord
|
|||
*/
|
||||
private InetAddress address;
|
||||
|
||||
/**
|
||||
* Session timeout in seconds.
|
||||
*/
|
||||
private Integer sessionTimeout;
|
||||
|
||||
/**
|
||||
* Context path of the application.
|
||||
*/
|
||||
|
@ -87,6 +89,8 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord
|
|||
*/
|
||||
private String displayName = "application";
|
||||
|
||||
private Session session = new Session();
|
||||
|
||||
@NestedConfigurationProperty
|
||||
private Ssl ssl;
|
||||
|
||||
|
@ -192,12 +196,28 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord
|
|||
this.address = address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the session timeout
|
||||
* @return the session timeout
|
||||
* @deprecated since 1.3.0 in favor of {@code session.timeout}.
|
||||
*/
|
||||
@Deprecated
|
||||
public Integer getSessionTimeout() {
|
||||
return this.sessionTimeout;
|
||||
return this.session.getTimeout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the session timeout
|
||||
* @param sessionTimeout the session timeout
|
||||
* @deprecated since 1.3.0 in favor of {@code session.timeout}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setSessionTimeout(Integer sessionTimeout) {
|
||||
this.sessionTimeout = sessionTimeout;
|
||||
this.session.setTimeout(sessionTimeout);
|
||||
}
|
||||
|
||||
public Session getSession() {
|
||||
return this.session;
|
||||
}
|
||||
|
||||
public Ssl getSsl() {
|
||||
|
@ -238,8 +258,8 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord
|
|||
if (getDisplayName() != null) {
|
||||
container.setDisplayName(getDisplayName());
|
||||
}
|
||||
if (getSessionTimeout() != null) {
|
||||
container.setSessionTimeout(getSessionTimeout());
|
||||
if (getSession().getTimeout() != null) {
|
||||
container.setSessionTimeout(getSession().getTimeout());
|
||||
}
|
||||
if (getSsl() != null) {
|
||||
container.setSsl(getSsl());
|
||||
|
@ -258,6 +278,7 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord
|
|||
getUndertow().customizeUndertow(
|
||||
(UndertowEmbeddedServletContainerFactory) container);
|
||||
}
|
||||
container.addInitializers(new SessionConfiguringInitializer(this.session));
|
||||
container.addInitializers(new InitParameterConfiguringServletContextInitializer(
|
||||
getContextParameters()));
|
||||
}
|
||||
|
@ -288,6 +309,137 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord
|
|||
return prefix + path;
|
||||
}
|
||||
|
||||
public static class Session {
|
||||
|
||||
/**
|
||||
* Session timeout in seconds.
|
||||
*/
|
||||
private Integer timeout;
|
||||
|
||||
/**
|
||||
* Session tracking modes (one or more of the following: "cookie", "url", "ssl")
|
||||
*/
|
||||
private Set<SessionTrackingMode> trackingModes;
|
||||
|
||||
private Cookie cookie = new Cookie();
|
||||
|
||||
public Cookie getCookie() {
|
||||
return this.cookie;
|
||||
}
|
||||
|
||||
public Integer getTimeout() {
|
||||
return this.timeout;
|
||||
}
|
||||
|
||||
public void setTimeout(Integer sessionTimeout) {
|
||||
this.timeout = sessionTimeout;
|
||||
}
|
||||
|
||||
public Set<SessionTrackingMode> getTrackingModes() {
|
||||
return this.trackingModes;
|
||||
}
|
||||
|
||||
public void setTrackingModes(Set<SessionTrackingMode> trackingModes) {
|
||||
this.trackingModes = trackingModes;
|
||||
}
|
||||
|
||||
public static class Cookie {
|
||||
|
||||
/**
|
||||
* Session cookie name.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Domain for the session cookie.
|
||||
*/
|
||||
private String domain;
|
||||
|
||||
/**
|
||||
* Path of the session cookie.
|
||||
*/
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* Comment for the session cookie.
|
||||
*/
|
||||
private String comment;
|
||||
|
||||
/**
|
||||
* "HttpOnly" flag for the session cookie.
|
||||
*/
|
||||
private Boolean httpOnly;
|
||||
|
||||
/**
|
||||
* "Secure" flag for the session cookie.
|
||||
*/
|
||||
private Boolean secure;
|
||||
|
||||
/**
|
||||
* Maximum age of the session cookie in seconds.
|
||||
*/
|
||||
private Integer maxAge;
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDomain() {
|
||||
return this.domain;
|
||||
}
|
||||
|
||||
public void setDomain(String domain) {
|
||||
this.domain = domain;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public String getComment() {
|
||||
return this.comment;
|
||||
}
|
||||
|
||||
public void setComment(String comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
public Boolean getHttpOnly() {
|
||||
return this.httpOnly;
|
||||
}
|
||||
|
||||
public void setHttpOnly(Boolean httpOnly) {
|
||||
this.httpOnly = httpOnly;
|
||||
}
|
||||
|
||||
public Boolean getSecure() {
|
||||
return this.secure;
|
||||
}
|
||||
|
||||
public void setSecure(Boolean secure) {
|
||||
this.secure = secure;
|
||||
}
|
||||
|
||||
public Integer getMaxAge() {
|
||||
return this.maxAge;
|
||||
}
|
||||
|
||||
public void setMaxAge(Integer maxAge) {
|
||||
this.maxAge = maxAge;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Tomcat {
|
||||
|
||||
/**
|
||||
|
@ -662,4 +814,51 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ServletContextInitializer} to apply appropriate parts of the {@link Session}
|
||||
* configuration.
|
||||
*/
|
||||
private static class SessionConfiguringInitializer implements
|
||||
ServletContextInitializer {
|
||||
|
||||
private final Session session;
|
||||
|
||||
public SessionConfiguringInitializer(Session session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartup(ServletContext servletContext) throws ServletException {
|
||||
if (this.session.getTrackingModes() != null) {
|
||||
servletContext.setSessionTrackingModes(this.session.getTrackingModes());
|
||||
}
|
||||
configureSessionCookie(servletContext.getSessionCookieConfig());
|
||||
}
|
||||
|
||||
private void configureSessionCookie(SessionCookieConfig config) {
|
||||
Cookie cookie = this.session.getCookie();
|
||||
if (cookie.getName() != null) {
|
||||
config.setName(cookie.getName());
|
||||
}
|
||||
if (cookie.getDomain() != null) {
|
||||
config.setDomain(cookie.getDomain());
|
||||
}
|
||||
if (cookie.getPath() != null) {
|
||||
config.setPath(cookie.getPath());
|
||||
}
|
||||
if (cookie.getComment() != null) {
|
||||
config.setComment(cookie.getComment());
|
||||
}
|
||||
if (cookie.getHttpOnly() != null) {
|
||||
config.setHttpOnly(cookie.getHttpOnly());
|
||||
}
|
||||
if (cookie.getSecure() != null) {
|
||||
config.setSecure(cookie.getSecure());
|
||||
}
|
||||
if (cookie.getMaxAge() != null) {
|
||||
config.setMaxAge(cookie.getMaxAge());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,6 +157,12 @@
|
|||
"type": "java.lang.String",
|
||||
"description": "Spring MVC view suffix.",
|
||||
"deprecated": true
|
||||
},
|
||||
{
|
||||
"name": "server.session-timeout",
|
||||
"type": "java.lang.Integer",
|
||||
"description": "Session timeout in seconds.",
|
||||
"deprecated": true
|
||||
}
|
||||
],"hints": [
|
||||
{
|
||||
|
|
|
@ -18,21 +18,34 @@ package org.springframework.boot.autoconfigure.web;
|
|||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.SessionCookieConfig;
|
||||
import javax.servlet.SessionTrackingMode;
|
||||
|
||||
import org.apache.catalina.Valve;
|
||||
import org.apache.catalina.valves.RemoteIpValve;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.boot.bind.RelaxedDataBinder;
|
||||
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.ServletContextInitializer;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||
|
||||
import static org.hamcrest.core.IsInstanceOf.instanceOf;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
@ -48,6 +61,14 @@ public class ServerPropertiesTests {
|
|||
|
||||
private final ServerProperties properties = new ServerProperties();
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<ServletContextInitializer[]> initializersCaptor;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddressBinding() throws Exception {
|
||||
RelaxedDataBinder binder = new RelaxedDataBinder(this.properties, "server");
|
||||
|
@ -123,6 +144,53 @@ public class ServerPropertiesTests {
|
|||
verify(factory).setDisplayName("TestName");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customizeSessionProperties() throws Exception {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("server.session.timeout", "123");
|
||||
map.put("server.session.tracking-modes", "cookie,url");
|
||||
map.put("server.session.cookie.name", "testname");
|
||||
map.put("server.session.cookie.domain", "testdomain");
|
||||
map.put("server.session.cookie.path", "/testpath");
|
||||
map.put("server.session.cookie.comment", "testcomment");
|
||||
map.put("server.session.cookie.http-only", "true");
|
||||
map.put("server.session.cookie.secure", "true");
|
||||
map.put("server.session.cookie.max-age", "60");
|
||||
bindProperties(map);
|
||||
ConfigurableEmbeddedServletContainer factory = mock(ConfigurableEmbeddedServletContainer.class);
|
||||
ServletContext servletContext = mock(ServletContext.class);
|
||||
SessionCookieConfig sessionCookieConfig = mock(SessionCookieConfig.class);
|
||||
given(servletContext.getSessionCookieConfig()).willReturn(sessionCookieConfig);
|
||||
this.properties.customize(factory);
|
||||
triggerInitializers(factory, servletContext);
|
||||
verify(factory).setSessionTimeout(123);
|
||||
verify(servletContext).setSessionTrackingModes(
|
||||
EnumSet.of(SessionTrackingMode.COOKIE, SessionTrackingMode.URL));
|
||||
verify(sessionCookieConfig).setName("testname");
|
||||
verify(sessionCookieConfig).setDomain("testdomain");
|
||||
verify(sessionCookieConfig).setPath("/testpath");
|
||||
verify(sessionCookieConfig).setComment("testcomment");
|
||||
verify(sessionCookieConfig).setHttpOnly(true);
|
||||
verify(sessionCookieConfig).setSecure(true);
|
||||
verify(sessionCookieConfig).setMaxAge(60);
|
||||
}
|
||||
|
||||
private void triggerInitializers(ConfigurableEmbeddedServletContainer container,
|
||||
ServletContext servletContext) throws ServletException {
|
||||
verify(container, atLeastOnce()).addInitializers(
|
||||
this.initializersCaptor.capture());
|
||||
for (Object initializers : this.initializersCaptor.getAllValues()) {
|
||||
if (initializers instanceof ServletContextInitializer) {
|
||||
((ServletContextInitializer) initializers).onStartup(servletContext);
|
||||
}
|
||||
else {
|
||||
for (ServletContextInitializer initializer : (ServletContextInitializer[]) initializers) {
|
||||
initializer.onStartup(servletContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomizeTomcatPort() throws Exception {
|
||||
ConfigurableEmbeddedServletContainer factory = mock(ConfigurableEmbeddedServletContainer.class);
|
||||
|
|
|
@ -65,7 +65,6 @@ content into your application; rather pick only the properties that you need.
|
|||
# EMBEDDED SERVER CONFIGURATION ({sc-spring-boot-autoconfigure}/web/ServerProperties.{sc-ext}[ServerProperties])
|
||||
server.port=8080
|
||||
server.address= # bind to a specific NIC
|
||||
server.session-timeout= # session timeout in seconds
|
||||
server.compression.enabled=false # if response compression is enabled
|
||||
server.compression.mime-types=text/html,text/xml,text/plain,text/css # comma-separated list of MIME types that should be compressed
|
||||
server.compression.min-response-size=2048 # minimum response size that is required for compression to be performed
|
||||
|
@ -76,6 +75,15 @@ content into your application; rather pick only the properties that you need.
|
|||
server.jsp-servlet.registered=true # Whether or not the JSP servlet is registered
|
||||
server.servlet-path= # the servlet path, defaults to '/'
|
||||
server.display-name= # the display name of the application
|
||||
server.session.timeout= # session timeout in seconds
|
||||
server.session.tracking-modes= # tracking modes (one or more of "cookie" ,"url", "ssl")
|
||||
server.session.cookie.name=
|
||||
server.session.cookie.domain=
|
||||
server.session.cookie.path=
|
||||
server.session.cookie.comment=
|
||||
server.session.cookie.http-only=
|
||||
server.session.cookie.secure=
|
||||
server.session.cookie.max-age=
|
||||
server.ssl.enabled=true # if SSL support is enabled
|
||||
server.ssl.client-auth= # want or need
|
||||
server.ssl.key-alias=
|
||||
|
|
Loading…
Reference in New Issue