diff --git a/build.gradle b/build.gradle index 1419ef3f..e553614a 100644 --- a/build.gradle +++ b/build.gradle @@ -17,6 +17,8 @@ ext.springBootVersion = '1.2.3.RELEASE' ext.JAVA_GRADLE = "$rootDir/gradle/java.gradle" ext.MAVEN_GRADLE = "$rootDir/gradle/publish-maven.gradle" ext.TOMCAT_GRADLE = "$rootDir/gradle/tomcat.gradle" +ext.TOMCAT_6_GRADLE = "$rootDir/gradle/tomcat6.gradle" +ext.TOMCAT_7_GRADLE = "$rootDir/gradle/tomcat7.gradle" ext.releaseBuild = version.endsWith('RELEASE') ext.snapshotBuild = version.endsWith('SNAPSHOT') diff --git a/gradle/tomcat.gradle b/gradle/tomcat.gradle index 0fb391eb..5d83bd33 100644 --- a/gradle/tomcat.gradle +++ b/gradle/tomcat.gradle @@ -10,15 +10,6 @@ buildscript { apply plugin: 'war' apply plugin: 'tomcat' -dependencies { - def tomcatVersion = '7.0.54' - tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}", - "org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}" - tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") { - exclude group: 'org.eclipse.jdt.core.compiler', module: 'ecj' - } -} - [tomcatRun,tomcatRunWar]*.contextPath = '/' diff --git a/gradle/tomcat6.gradle b/gradle/tomcat6.gradle new file mode 100644 index 00000000..964cb644 --- /dev/null +++ b/gradle/tomcat6.gradle @@ -0,0 +1,8 @@ +apply from: TOMCAT_GRADLE + +dependencies { + def tomcatVersion = '6.0.43' + tomcat "org.apache.tomcat:catalina:${tomcatVersion}", + "org.apache.tomcat:coyote:${tomcatVersion}", + "org.apache.tomcat:jasper:${tomcatVersion}" +} \ No newline at end of file diff --git a/gradle/tomcat7.gradle b/gradle/tomcat7.gradle new file mode 100644 index 00000000..c1a2c615 --- /dev/null +++ b/gradle/tomcat7.gradle @@ -0,0 +1,10 @@ +apply from: TOMCAT_GRADLE + +dependencies { + def tomcatVersion = '7.0.59' + tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}", + "org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}" + tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") { + exclude group: 'org.eclipse.jdt.core.compiler', module: 'ecj' + } +} \ No newline at end of file diff --git a/samples/hazelcast/build.gradle b/samples/hazelcast/build.gradle index cf29c063..6eca5f2f 100644 --- a/samples/hazelcast/build.gradle +++ b/samples/hazelcast/build.gradle @@ -1,5 +1,5 @@ apply from: JAVA_GRADLE -apply from: TOMCAT_GRADLE +apply from: TOMCAT_7_GRADLE tasks.findByPath("artifactoryPublish")?.enabled = false sonarRunner { diff --git a/samples/httpsession-xml/build.gradle b/samples/httpsession-xml/build.gradle index dfb00ba7..03d98aa0 100644 --- a/samples/httpsession-xml/build.gradle +++ b/samples/httpsession-xml/build.gradle @@ -1,5 +1,5 @@ apply from: JAVA_GRADLE -apply from: TOMCAT_GRADLE +apply from: TOMCAT_6_GRADLE tasks.findByPath("artifactoryPublish")?.enabled = false sonarRunner { diff --git a/samples/httpsession-xml/src/main/java/sample/SessionServlet.java b/samples/httpsession-xml/src/main/java/sample/SessionServlet.java index 3c510143..d93d6320 100644 --- a/samples/httpsession-xml/src/main/java/sample/SessionServlet.java +++ b/samples/httpsession-xml/src/main/java/sample/SessionServlet.java @@ -16,12 +16,10 @@ package sample; import javax.servlet.*; -import javax.servlet.annotation.*; import javax.servlet.http.*; import java.io.IOException; // tag::class[] -@WebServlet("/session") public class SessionServlet extends HttpServlet { @Override diff --git a/samples/httpsession-xml/src/main/webapp/WEB-INF/web.xml b/samples/httpsession-xml/src/main/webapp/WEB-INF/web.xml index 6e07a6ed..ad259395 100644 --- a/samples/httpsession-xml/src/main/webapp/WEB-INF/web.xml +++ b/samples/httpsession-xml/src/main/webapp/WEB-INF/web.xml @@ -1,11 +1,11 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> + - Location of the XML file that defines the root application context + - Applied by ContextLoaderListener. + --> contextConfigLocation @@ -24,14 +24,24 @@ org.springframework.web.context.ContextLoaderListener + + session + sample.SessionServlet + + + + session + /session + + index.jsp diff --git a/samples/httpsession/build.gradle b/samples/httpsession/build.gradle index dfb00ba7..758d7276 100644 --- a/samples/httpsession/build.gradle +++ b/samples/httpsession/build.gradle @@ -1,5 +1,5 @@ apply from: JAVA_GRADLE -apply from: TOMCAT_GRADLE +apply from: TOMCAT_7_GRADLE tasks.findByPath("artifactoryPublish")?.enabled = false sonarRunner { diff --git a/samples/rest/build.gradle b/samples/rest/build.gradle index 07f5bc99..c459854a 100644 --- a/samples/rest/build.gradle +++ b/samples/rest/build.gradle @@ -1,5 +1,5 @@ apply from: JAVA_GRADLE -apply from: TOMCAT_GRADLE +apply from: TOMCAT_7_GRADLE tasks.findByPath("artifactoryPublish")?.enabled = false sonarRunner { diff --git a/samples/security/build.gradle b/samples/security/build.gradle index b97f71ac..5ded8deb 100644 --- a/samples/security/build.gradle +++ b/samples/security/build.gradle @@ -1,5 +1,5 @@ apply from: JAVA_GRADLE -apply from: TOMCAT_GRADLE +apply from: TOMCAT_7_GRADLE tasks.findByPath("artifactoryPublish")?.enabled = false sonarRunner { diff --git a/samples/users/build.gradle b/samples/users/build.gradle index dfb00ba7..758d7276 100644 --- a/samples/users/build.gradle +++ b/samples/users/build.gradle @@ -1,5 +1,5 @@ apply from: JAVA_GRADLE -apply from: TOMCAT_GRADLE +apply from: TOMCAT_7_GRADLE tasks.findByPath("artifactoryPublish")?.enabled = false sonarRunner { diff --git a/samples/websocket/build.gradle b/samples/websocket/build.gradle index 137376ba..39fab1dd 100644 --- a/samples/websocket/build.gradle +++ b/samples/websocket/build.gradle @@ -10,7 +10,7 @@ buildscript { apply plugin: 'spring-boot' apply from: JAVA_GRADLE -apply from: TOMCAT_GRADLE +apply from: TOMCAT_7_GRADLE tasks.findByPath("artifactoryPublish")?.enabled = false diff --git a/spring-session/src/integration-test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryITests.java b/spring-session/src/integration-test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryITests.java index 61e3571e..b824a018 100644 --- a/spring-session/src/integration-test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryITests.java +++ b/spring-session/src/integration-test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryITests.java @@ -45,11 +45,13 @@ import org.springframework.session.data.redis.config.annotation.web.http.EnableR import org.springframework.session.events.SessionDestroyedEvent; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; import redis.embedded.RedisServer; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration +@WebAppConfiguration public class RedisOperationsSessionRepositoryITests { @Autowired private SessionRepository repository; diff --git a/spring-session/src/integration-test/java/org/springframework/session/data/redis/config/annotation/web/http/EnableRedisHttpSessionExpireSessionDestroyedTests.java b/spring-session/src/integration-test/java/org/springframework/session/data/redis/config/annotation/web/http/EnableRedisHttpSessionExpireSessionDestroyedTests.java index d0887d07..a6b568bd 100644 --- a/spring-session/src/integration-test/java/org/springframework/session/data/redis/config/annotation/web/http/EnableRedisHttpSessionExpireSessionDestroyedTests.java +++ b/spring-session/src/integration-test/java/org/springframework/session/data/redis/config/annotation/web/http/EnableRedisHttpSessionExpireSessionDestroyedTests.java @@ -45,11 +45,13 @@ import org.springframework.session.SessionRepository; import org.springframework.session.events.SessionDestroyedEvent; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; import redis.embedded.RedisServer; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration +@WebAppConfiguration public class EnableRedisHttpSessionExpireSessionDestroyedTests { @Autowired private SessionRepository repository; diff --git a/spring-session/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java b/spring-session/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java index 30e42624..42c8555b 100644 --- a/spring-session/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java +++ b/spring-session/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java @@ -19,6 +19,8 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import javax.servlet.ServletContext; + import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; @@ -99,8 +101,9 @@ public class RedisHttpSessionConfiguration implements ImportAware, BeanClassLoad } @Bean - public SessionRepositoryFilter springSessionRepositoryFilter(SessionRepository sessionRepository) { + public SessionRepositoryFilter springSessionRepositoryFilter(SessionRepository sessionRepository, ServletContext servletContext) { SessionRepositoryFilter sessionRepositoryFilter = new SessionRepositoryFilter(sessionRepository); + sessionRepositoryFilter.setServletContext(servletContext); if(httpSessionStrategy != null) { sessionRepositoryFilter.setHttpSessionStrategy(httpSessionStrategy); } diff --git a/spring-session/src/main/java/org/springframework/session/web/http/CookieHttpSessionStrategy.java b/spring-session/src/main/java/org/springframework/session/web/http/CookieHttpSessionStrategy.java index 515cbaa6..439ad3b6 100644 --- a/spring-session/src/main/java/org/springframework/session/web/http/CookieHttpSessionStrategy.java +++ b/spring-session/src/main/java/org/springframework/session/web/http/CookieHttpSessionStrategy.java @@ -23,6 +23,7 @@ import java.util.Set; import java.util.StringTokenizer; import java.util.regex.Pattern; +import javax.servlet.ServletRequest; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -161,6 +162,8 @@ public final class CookieHttpSessionStrategy implements MultiHttpSessionStrategy private String sessionParam = DEFAULT_SESSION_ALIAS_PARAM_NAME; + private boolean isServlet3Plus = isServlet3(); + public String getRequestedSessionId(HttpServletRequest request) { Map sessionIds = getSessionIds(request); String sessionAlias = getCurrentSessionAlias(request); @@ -215,7 +218,9 @@ public final class CookieHttpSessionStrategy implements MultiHttpSessionStrategy private Cookie createSessionCookie(HttpServletRequest request, Map sessionIds) { Cookie sessionCookie = new Cookie(cookieName,""); - sessionCookie.setHttpOnly(true); + if(isServlet3Plus) { + sessionCookie.setHttpOnly(true); + } sessionCookie.setSecure(request.isSecure()); sessionCookie.setPath(cookiePath(request)); // TODO set domain? @@ -387,4 +392,16 @@ public final class CookieHttpSessionStrategy implements MultiHttpSessionStrategy throw new RuntimeException(e); } } + + /** + * Returns true if the Servlet 3 APIs are detected. + * @return + */ + private boolean isServlet3() { + try { + ServletRequest.class.getMethod("startAsync"); + return true; + } catch(NoSuchMethodException e) {} + return false; + } } \ No newline at end of file diff --git a/spring-session/src/main/java/org/springframework/session/web/http/SessionRepositoryFilter.java b/spring-session/src/main/java/org/springframework/session/web/http/SessionRepositoryFilter.java index 07567643..7ce2cc1a 100644 --- a/spring-session/src/main/java/org/springframework/session/web/http/SessionRepositoryFilter.java +++ b/spring-session/src/main/java/org/springframework/session/web/http/SessionRepositoryFilter.java @@ -66,6 +66,8 @@ public class SessionRepositoryFilter extends OncePerR private final SessionRepository sessionRepository; + private ServletContext servletContext; + private MultiHttpSessionStrategy httpSessionStrategy = new CookieHttpSessionStrategy(); /** @@ -107,7 +109,7 @@ public class SessionRepositoryFilter extends OncePerR protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { request.setAttribute(SESSION_REPOSITORY_ATTR, sessionRepository); - SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(request, response); + SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(request, response, servletContext); SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(wrappedRequest,response); HttpServletRequest strategyRequest = httpSessionStrategy.wrapRequest(wrappedRequest, wrappedResponse); @@ -120,6 +122,10 @@ public class SessionRepositoryFilter extends OncePerR } } + public void setServletContext(ServletContext servletContext) { + this.servletContext = servletContext; + } + /** * Allows ensuring that the session is saved if the response is committed. * @@ -158,10 +164,12 @@ public class SessionRepositoryFilter extends OncePerR private HttpSessionWrapper currentSession; private Boolean requestedSessionIdValid; private final HttpServletResponse response; + private final ServletContext servletContext; - private SessionRepositoryRequestWrapper(HttpServletRequest request, HttpServletResponse response) { + private SessionRepositoryRequestWrapper(HttpServletRequest request, HttpServletResponse response, ServletContext servletContext) { super(request); this.response = response; + this.servletContext = servletContext; } /** @@ -257,6 +265,14 @@ public class SessionRepositoryFilter extends OncePerR return currentSession; } + public ServletContext getServletContext() { + if(servletContext != null) { + return servletContext; + } + // Servlet 3.0+ + return super.getServletContext(); + } + @Override public HttpSession getSession() { return getSession(true); diff --git a/spring-session/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationXmlCustomExpireTests.java b/spring-session/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationXmlCustomExpireTests.java index 49267514..99e62136 100644 --- a/spring-session/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationXmlCustomExpireTests.java +++ b/spring-session/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationXmlCustomExpireTests.java @@ -24,9 +24,11 @@ import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration +@WebAppConfiguration public class RedisHttpSessionConfigurationXmlCustomExpireTests { @Test diff --git a/spring-session/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationXmlTests.java b/spring-session/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationXmlTests.java index dd9b725b..08ca2ecb 100644 --- a/spring-session/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationXmlTests.java +++ b/spring-session/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationXmlTests.java @@ -24,9 +24,11 @@ import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration +@WebAppConfiguration public class RedisHttpSessionConfigurationXmlTests { @Test diff --git a/spring-session/src/test/java/org/springframework/session/web/http/SessionRepositoryFilterTests.java b/spring-session/src/test/java/org/springframework/session/web/http/SessionRepositoryFilterTests.java index 1df10912..c724a962 100644 --- a/spring-session/src/test/java/org/springframework/session/web/http/SessionRepositoryFilterTests.java +++ b/spring-session/src/test/java/org/springframework/session/web/http/SessionRepositoryFilterTests.java @@ -50,6 +50,7 @@ import org.springframework.core.annotation.OrderUtils; import org.springframework.mock.web.MockFilterChain; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.mock.web.MockServletContext; import org.springframework.session.ExpiringSession; import org.springframework.session.MapSessionRepository; import org.springframework.session.Session; @@ -188,6 +189,22 @@ public class SessionRepositoryFilterTests { }); } + // gh-111 + @Test + public void doFilterServletContextExplicit() throws Exception { + final ServletContext expectedContext = new MockServletContext(); + filter = new SessionRepositoryFilter(sessionRepository); + filter.setServletContext(expectedContext); + + doFilter(new DoInFilter() { + @Override + public void doFilter(HttpServletRequest wrappedRequest) { + ServletContext context = wrappedRequest.getSession().getServletContext(); + assertThat(context).isSameAs(expectedContext); + } + }); + } + @Test public void doFilterMaxInactiveIntervalDefault() throws Exception { doFilter(new DoInFilter() {