Merge pull request #14656 from manfred106/BAEL-6848-jsp-set-param

BAEL-6848: Set a Parameter in a HttpServletRequest in Java
This commit is contained in:
Liam Williams 2023-08-26 23:01:08 +01:00 committed by GitHub
commit ffddf2b07f
13 changed files with 411 additions and 0 deletions

View File

@ -22,6 +22,11 @@
<artifactId>commons-fileupload</artifactId> <artifactId>commons-fileupload</artifactId>
<version>${commons-fileupload.version}</version> <version>${commons-fileupload.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>${commons-text.version}</version>
</dependency>
<!-- Servlet --> <!-- Servlet -->
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
@ -76,6 +81,16 @@
</argLine> </argLine>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${jetty-maven-plugin.version}</version>
<configuration>
<webApp>
<contextPath>/</contextPath>
</webApp>
</configuration>
</plugin>
</plugins> </plugins>
</build> </build>
@ -84,6 +99,8 @@
<jmockit.version>1.49</jmockit.version> <jmockit.version>1.49</jmockit.version>
<spring-test.version>5.3.20</spring-test.version> <spring-test.version>5.3.20</spring-test.version>
<maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version> <maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
<jetty-maven-plugin.version>10.0.4</jetty-maven-plugin.version>
<commons-text.version>1.10.0</commons-text.version>
</properties> </properties>
</project> </project>

View File

@ -0,0 +1,21 @@
package com.baeldung.setparam;
import java.io.IOException;
import java.util.Locale;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
@WebServlet(name = "LanguageServlet", urlPatterns = "/setparam/lang")
public class LanguageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
SetParameterRequestWrapper requestWrapper = new SetParameterRequestWrapper(request);
requestWrapper.setParameter("locale", Locale.getDefault().getLanguage());
request.getRequestDispatcher("/setparam/3rd_party_module.jsp").forward(requestWrapper, response);
}
}

View File

@ -0,0 +1,17 @@
package com.baeldung.setparam;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
@WebFilter(urlPatterns = { "/setparam/with-sanitize.jsp" })
public class SanitizeParametersFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest) request;
chain.doFilter(new SanitizeParametersRequestWrapper(httpReq), response);
}
}

View File

@ -0,0 +1,46 @@
package com.baeldung.setparam;
import java.util.*;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.text.StringEscapeUtils;
public class SanitizeParametersRequestWrapper extends HttpServletRequestWrapper {
private final Map<String, String[]> sanitizedMap;
public SanitizeParametersRequestWrapper(HttpServletRequest request) {
super(request);
sanitizedMap = Collections.unmodifiableMap(
request.getParameterMap().entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> Arrays.stream(entry.getValue())
.map(StringEscapeUtils::escapeHtml4)
.toArray(String[]::new)
)));
}
@Override
public Map<String, String[]> getParameterMap() {
return sanitizedMap;
}
@Override
public String[] getParameterValues(String name) {
return Optional.ofNullable(getParameterMap().get(name))
.map(values -> Arrays.copyOf(values, values.length))
.orElse(null);
}
@Override
public String getParameter(String name) {
return Optional.ofNullable(getParameterValues(name))
.map(values -> values[0])
.orElse(null);
}
}

View File

@ -0,0 +1,40 @@
package com.baeldung.setparam;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class SetParameterRequestWrapper extends HttpServletRequestWrapper {
private final Map<String, String[]> paramMap;
public SetParameterRequestWrapper(HttpServletRequest request) {
super(request);
paramMap = new HashMap<>(request.getParameterMap());
}
@Override
public Map<String, String[]> getParameterMap() {
return Collections.unmodifiableMap(paramMap);
}
@Override
public String[] getParameterValues(String name) {
return Optional.ofNullable(getParameterMap().get(name))
.map(values -> Arrays.copyOf(values, values.length))
.orElse(null);
}
@Override
public String getParameter(String name) {
return Optional.ofNullable(getParameterValues(name))
.map(values -> values[0])
.orElse(null);
}
public void setParameter(String name, String value) {
paramMap.put(name, new String[] {value});
}
}

View File

@ -0,0 +1,13 @@
<%@ page import="java.util.*"%>
<html>
<head>
<title>3rd party Module</title>
</head>
<body>
<%
String localeStr = request.getParameter("locale");
Locale currentLocale = (localeStr != null ? new Locale(localeStr) : null);
%>
The language you have selected: <%=currentLocale != null ? currentLocale.getDisplayLanguage(currentLocale) : " None"%>
</body>
</html>

View File

@ -0,0 +1,10 @@
<html>
<head>
<title>Sanitized request parameter</title>
</head>
<body>
The text below comes from request parameter "input":
<br/>
<%=request.getParameter("input")%>
</body>
</html>

View File

@ -0,0 +1,10 @@
<html>
<head>
<title>Non sanitized request parameter</title>
</head>
<body>
The text below comes from request parameter "input":
<br/>
<%=request.getParameter("input")%>
</body>
</html>

View File

@ -0,0 +1,34 @@
package com.baeldung.setparam;
import static org.junit.Assert.assertTrue;
import java.util.Locale;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
public class LanguageServletIntegrationTest {
@Test
public void whenGetRequestUsingHttpClient_thenResponseBodyContainsDefaultLanguage() throws Exception {
// When
HttpClient client = HttpClientBuilder.create().build();
HttpGet method = new HttpGet("http://localhost:8080/setparam/lang");
HttpResponse httpResponse = client.execute(method);
// Then
Locale defaultLocale = Locale.getDefault();
String expectedLanguage = defaultLocale.getDisplayLanguage(defaultLocale);
HttpEntity entity = httpResponse.getEntity();
String responseBody = EntityUtils.toString(entity, "UTF-8");
assertTrue(responseBody.contains("The language you have selected: " + expectedLanguage));
}
}

View File

@ -0,0 +1,40 @@
package com.baeldung.setparam;
import static org.junit.Assert.assertTrue;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.junit.BeforeClass;
import org.junit.Test;
public class SanitizeParametersRequestIntegrationTest {
private static String PARAM_INPUT;
@BeforeClass
public static void init() throws UnsupportedEncodingException {
PARAM_INPUT = URLEncoder.encode("<script>alert('Hello');</script>", "UTF-8");
}
@Test
public void whenInputParameterContainsXss_thenResponseBodyContainsSanitizedValue() throws Exception {
// When
HttpClient client = HttpClientBuilder.create().build();
HttpGet method = new HttpGet(String.format("http://localhost:8080/setparam/with-sanitize.jsp?input=%s", PARAM_INPUT));
HttpResponse httpResponse = client.execute(method);
// Then
HttpEntity entity = httpResponse.getEntity();
String responseBody = EntityUtils.toString(entity, "UTF-8");
assertTrue(responseBody.contains("&lt;script&gt;alert('Hello');&lt;/script&gt;"));
}
}

View File

@ -0,0 +1,60 @@
package com.baeldung.setparam;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.mockito.Mockito.when;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class SanitizeParametersRequestWrapperUnitTest {
private String NEW_VALUE = "NEW VALUE";
private Map<String, String[]> parameterMap;
@Mock
private HttpServletRequest request;
@Before
public void initBeforeEachTest() {
parameterMap = new HashMap<>();
parameterMap.put("input", new String[] {"<script>alert('Hello');</script>"});
when(request.getParameterMap()).thenReturn(parameterMap);
}
@Test
public void whenGetParameterViaWrapper_thenParameterReturnedIsSanitized() {
SanitizeParametersRequestWrapper wrapper = new SanitizeParametersRequestWrapper(request);
String actualValue = wrapper.getParameter("input");
assertEquals(actualValue, "&lt;script&gt;alert('Hello');&lt;/script&gt;");
}
@Test(expected = UnsupportedOperationException.class)
public void whenPutValueToWrapperParameterMap_thenThrowsUnsupportedOperationException() {
SanitizeParametersRequestWrapper wrapper = new SanitizeParametersRequestWrapper(request);
Map<String, String[]> wrapperParamMap = wrapper.getParameterMap();
wrapperParamMap.put("input", new String[] {NEW_VALUE});
}
@Test
public void whenSetValueToWrapperParametersStringArray_thenThe2ndCallShouldNotEqualToNewValue() {
SanitizeParametersRequestWrapper wrapper = new SanitizeParametersRequestWrapper(request);
String[] firstCallValues = wrapper.getParameterValues("input");
firstCallValues[0] = NEW_VALUE;
String[] secondCallValues = wrapper.getParameterValues("input");
assertNotEquals(firstCallValues, secondCallValues);
}
}

View File

@ -0,0 +1,61 @@
package com.baeldung.setparam;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.mockito.Mockito.when;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class SetParameterRequestWrapperUnitTest {
private String NEW_VALUE = "NEW VALUE";
private Map<String, String[]> parameterMap;
@Mock
private HttpServletRequest request;
@Before
public void initBeforeEachTest() {
parameterMap = new HashMap<>();
parameterMap.put("input", new String[] {"inputValue"});
when(request.getParameterMap()).thenReturn(parameterMap);
}
@Test
public void whenSetParameterViaWrapper_thenGetParameterShouldReturnTheSameValue() {
SetParameterRequestWrapper wrapper = new SetParameterRequestWrapper(request);
wrapper.setParameter("newInput", "newInputValue");
String actualValue = wrapper.getParameter("newInput");
assertEquals(actualValue, "newInputValue");
}
@Test(expected = UnsupportedOperationException.class)
public void whenPutValueToWrapperParameterMap_thenThrowsUnsupportedOperationException() {
SetParameterRequestWrapper wrapper = new SetParameterRequestWrapper(request);
Map<String, String[]> wrapperParamMap = wrapper.getParameterMap();
wrapperParamMap.put("input", new String[] {NEW_VALUE});
}
@Test
public void whenSetValueToWrapperParametersStringArray_thenThe2ndCallShouldNotEqualToNewValue() {
SetParameterRequestWrapper wrapper = new SetParameterRequestWrapper(request);
String[] firstCallValues = wrapper.getParameterValues("input");
firstCallValues[0] = NEW_VALUE;
String[] secondCallValues = wrapper.getParameterValues("input");
assertNotEquals(firstCallValues, secondCallValues);
}
}

View File

@ -0,0 +1,42 @@
package com.baeldung.setparam;
import static org.junit.Assert.assertTrue;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.junit.BeforeClass;
import org.junit.Test;
public class UnsanitizedParametersRequestIntegrationTest {
private static final String TAG_SCRIPT = "<script>alert('Hello');</script>";
private static String PARAM_INPUT;
@BeforeClass
public static void init() throws UnsupportedEncodingException {
PARAM_INPUT = URLEncoder.encode(TAG_SCRIPT, "UTF-8");
}
@Test
public void whenInputParameterContainsXss_thenResponseBodyContainsUnsanitizedValue() throws Exception {
// When
HttpClient client = HttpClientBuilder.create().build();
HttpGet method = new HttpGet(String.format("http://localhost:8080/setparam/without-sanitize.jsp?input=%s", PARAM_INPUT));
HttpResponse httpResponse = client.execute(method);
// Then
HttpEntity entity = httpResponse.getEntity();
String responseBody = EntityUtils.toString(entity, "UTF-8");
assertTrue(responseBody.contains(TAG_SCRIPT));
}
}