aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2016-09-06 12:23:50 +0200
committerJulien Lancelot <julien.lancelot@sonarsource.com>2016-09-09 10:10:51 +0200
commit79c3bfc01953b03cee1e0bf210cf11734ce9ef24 (patch)
treefe0281dcd08b15d9ae5bb40a02a3ad20afd8066c
parent59de2c0352b71a93c8d1191efdaa9e672e8c7b5f (diff)
downloadsonarqube-79c3bfc01953b03cee1e0bf210cf11734ce9ef24.tar.gz
sonarqube-79c3bfc01953b03cee1e0bf210cf11734ce9ef24.zip
SONAR-7714 Remove JSESSIONID generation from Tomcat
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/app/TomcatContexts.java1
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/web/MasterServletFilter.java5
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/web/RootFilter.java (renamed from server/sonar-server/src/main/java/org/sonar/server/platform/web/ProfilingFilter.java)45
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/web/MasterServletFilterTest.java15
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/web/RootFilterTest.java (renamed from server/sonar-server/src/test/java/org/sonar/server/platform/web/ProfilingFilterTest.java)62
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/web.xml14
6 files changed, 104 insertions, 38 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/app/TomcatContexts.java b/server/sonar-server/src/main/java/org/sonar/server/app/TomcatContexts.java
index 56dcf66f5ff..b15d76e0854 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/app/TomcatContexts.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/app/TomcatContexts.java
@@ -112,6 +112,7 @@ public class TomcatContexts {
context.setDelegate(true);
context.setJarScanner(new NullJarScanner());
context.setAllowCasualMultipartParsing(true);
+ context.setCookies(false);
return context;
} catch (ServletException e) {
throw new IllegalStateException("Fail to configure webapp from " + dir, e);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/web/MasterServletFilter.java b/server/sonar-server/src/main/java/org/sonar/server/platform/web/MasterServletFilter.java
index 76f3abd0822..230bddd3cd6 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/web/MasterServletFilter.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/web/MasterServletFilter.java
@@ -82,7 +82,7 @@ public class MasterServletFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpServletRequest hsr = (HttpServletRequest) request;
if (filters.length == 0) {
- chain.doFilter(request, response);
+ chain.doFilter(hsr, response);
} else {
String path = hsr.getRequestURI().replaceFirst(hsr.getContextPath(), "");
GodFilterChain godChain = new GodFilterChain(chain);
@@ -92,7 +92,7 @@ public class MasterServletFilter implements Filter {
godChain.addFilter(filter);
}
}
- godChain.doFilter(request, response);
+ godChain.doFilter(hsr, response);
}
}
@@ -134,4 +134,5 @@ public class MasterServletFilter implements Filter {
filters.add(filter);
}
}
+
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/web/ProfilingFilter.java b/server/sonar-server/src/main/java/org/sonar/server/platform/web/RootFilter.java
index 8728a7b401c..dec5a8d76c1 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/web/ProfilingFilter.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/web/RootFilter.java
@@ -19,11 +19,10 @@
*/
package org.sonar.server.platform.web;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.api.utils.log.Profiler;
-
+import java.io.IOException;
+import java.util.Set;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
@@ -31,9 +30,11 @@ import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
-
-import java.io.IOException;
-import java.util.Set;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpSession;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.api.utils.log.Profiler;
/**
* <p>Profile HTTP requests using platform profiling utility.</p>
@@ -44,7 +45,7 @@ import java.util.Set;
*
* @since 4.1
*/
-public class ProfilingFilter implements Filter {
+public class RootFilter implements Filter {
private static final String CONFIG_SEPARATOR = ",";
private static final String URL_SEPARATOR = "/";
@@ -71,17 +72,17 @@ public class ProfilingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (request instanceof HttpServletRequest) {
- HttpServletRequest httpRequest = (HttpServletRequest) request;
+ HttpServletRequest httpRequest = new ServletRequestWrapper((HttpServletRequest) request);
String requestUri = httpRequest.getRequestURI();
String rootDir = getRootDir(requestUri);
if (staticResourceDirs.contains(rootDir)) {
// Static resource, not profiled
- chain.doFilter(request, response);
+ chain.doFilter(httpRequest, response);
} else {
Profiler profiler = Profiler.createIfDebug(Logger).start();
try {
- chain.doFilter(request, response);
+ chain.doFilter(httpRequest, response);
} finally {
if (profiler.isDebugEnabled()) {
String queryString = httpRequest.getQueryString();
@@ -112,4 +113,26 @@ public class ProfilingFilter implements Filter {
public void destroy() {
// Nothing
}
+
+ @VisibleForTesting
+ static class ServletRequestWrapper extends HttpServletRequestWrapper {
+
+ ServletRequestWrapper(HttpServletRequest request) {
+ super(request);
+ }
+
+ @Override
+ public HttpSession getSession(boolean create) {
+ throw notSupported();
+ }
+
+ @Override
+ public HttpSession getSession() {
+ throw notSupported();
+ }
+
+ private static UnsupportedOperationException notSupported() {
+ return new UnsupportedOperationException("Sessions are disabled so that web server is stateless");
+ }
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/web/MasterServletFilterTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/web/MasterServletFilterTest.java
index 255dab8f8e3..3ac703c5819 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/platform/web/MasterServletFilterTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/web/MasterServletFilterTest.java
@@ -46,7 +46,7 @@ import static org.mockito.Mockito.when;
public class MasterServletFilterTest {
@Rule
- public ExpectedException thrown = ExpectedException.none();
+ public ExpectedException expectedException = ExpectedException.none();
@Before
public void resetSingleton() {
@@ -71,15 +71,15 @@ public class MasterServletFilterTest {
public void servlet_container_should_instantiate_only_a_single_master_instance() {
new MasterServletFilter();
- thrown.expect(IllegalStateException.class);
- thrown.expectMessage("Servlet filter org.sonar.server.platform.web.MasterServletFilter is already instantiated");
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("Servlet filter org.sonar.server.platform.web.MasterServletFilter is already instantiated");
new MasterServletFilter();
}
@Test
public void should_propagate_initialization_failure() throws Exception {
- thrown.expect(IllegalStateException.class);
- thrown.expectMessage("foo");
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("foo");
ServletFilter filter = mock(ServletFilter.class);
doThrow(new IllegalStateException("foo")).when(filter).init(any(FilterConfig.class));
@@ -126,17 +126,20 @@ public class MasterServletFilterTest {
private static int globalCount = 0;
private int count = 0;
+ @Override
public void init(FilterConfig filterConfig) throws ServletException {
}
+ @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
globalCount++;
count = globalCount;
filterChain.doFilter(servletRequest, servletResponse);
}
+ @Override
public void destroy() {
}
-
}
+
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/web/ProfilingFilterTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/web/RootFilterTest.java
index 93c339c9986..aff2ff1b642 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/platform/web/ProfilingFilterTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/web/RootFilterTest.java
@@ -19,10 +19,6 @@
*/
package org.sonar.server.platform.web;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
@@ -30,15 +26,25 @@ import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
-import org.sonar.server.platform.web.ProfilingFilter;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import static org.assertj.core.api.Java6Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-public class ProfilingFilterTest {
+public class RootFilterTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
- private ProfilingFilter filter;
+ private RootFilter filter;
private FilterChain chain;
@Before
@@ -50,7 +56,7 @@ public class ProfilingFilterTest {
when(filterConfig.getServletContext()).thenReturn(context);
chain = mock(FilterChain.class);
- filter = new ProfilingFilter();
+ filter = new RootFilter();
filter.init(filterConfig);
}
@@ -96,6 +102,46 @@ public class ProfilingFilterTest {
filter.doFilter(request("GET", "/context/static/image.png", null), null, chain);
}
+ @Test
+ public void request_used_in_chain_do_filter_is_a_servlet_wrapper_when_static_resource() throws Exception {
+ filter.doFilter(request("GET", "/context/static/image.png", null), null, chain);
+ ArgumentCaptor<ServletRequest> requestArgumentCaptor = ArgumentCaptor.forClass(ServletRequest.class);
+
+ verify(chain).doFilter(requestArgumentCaptor.capture(), any(ServletResponse.class));
+
+ assertThat(requestArgumentCaptor.getValue()).isInstanceOf(RootFilter.ServletRequestWrapper.class);
+ }
+
+ @Test
+ public void request_used_in_chain_do_filter_is_a_servlet_wrapper_when_service_call() throws Exception {
+ filter.doFilter(request("POST", "/context/service/call", "param=value"), null, chain);
+ ArgumentCaptor<ServletRequest> requestArgumentCaptor = ArgumentCaptor.forClass(ServletRequest.class);
+
+ verify(chain).doFilter(requestArgumentCaptor.capture(), any(ServletResponse.class));
+
+ assertThat(requestArgumentCaptor.getValue()).isInstanceOf(RootFilter.ServletRequestWrapper.class);
+ }
+
+ @Test
+ public void fail_to_get_session_from_request() throws Exception {
+ filter.doFilter(request("GET", "/context/static/image.png", null), null, chain);
+ ArgumentCaptor<ServletRequest> requestArgumentCaptor = ArgumentCaptor.forClass(ServletRequest.class);
+ verify(chain).doFilter(requestArgumentCaptor.capture(), any(ServletResponse.class));
+
+ expectedException.expect(UnsupportedOperationException.class);
+ ((HttpServletRequest) requestArgumentCaptor.getValue()).getSession();
+ }
+
+ @Test
+ public void fail_to_get_session_with_create_from_request() throws Exception {
+ filter.doFilter(request("GET", "/context/static/image.png", null), null, chain);
+ ArgumentCaptor<ServletRequest> requestArgumentCaptor = ArgumentCaptor.forClass(ServletRequest.class);
+ verify(chain).doFilter(requestArgumentCaptor.capture(), any(ServletResponse.class));
+
+ expectedException.expect(UnsupportedOperationException.class);
+ ((HttpServletRequest) requestArgumentCaptor.getValue()).getSession(true);
+ }
+
private HttpServletRequest request(String method, String path, String query) {
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getMethod()).thenReturn(method);
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/web.xml b/server/sonar-web/src/main/webapp/WEB-INF/web.xml
index b86c1a99b9b..e0bd48e3257 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/web.xml
+++ b/server/sonar-web/src/main/webapp/WEB-INF/web.xml
@@ -53,8 +53,8 @@
<filter-class>org.sonar.server.platform.web.SecurityServletFilter</filter-class>
</filter>
<filter>
- <filter-name>ProfilingFilter</filter-name>
- <filter-class>org.sonar.server.platform.web.ProfilingFilter</filter-class>
+ <filter-name>RootFilter</filter-name>
+ <filter-class>org.sonar.server.platform.web.RootFilter</filter-class>
<init-param>
<param-name>staticDirs</param-name>
<param-value>/images,/javascripts,/stylesheets</param-value>
@@ -67,7 +67,7 @@
<!-- order of execution is important -->
<filter-mapping>
- <filter-name>ProfilingFilter</filter-name>
+ <filter-name>RootFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
@@ -101,14 +101,6 @@
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
- <session-config>
- <!-- in minutes -->
- <session-timeout>20</session-timeout>
- <cookie-config>
- <http-only>true</http-only>
- </cookie-config>
- </session-config>
-
<listener>
<listener-class>org.sonar.server.platform.web.PlatformServletContextListener</listener-class>
</listener>