diff --git a/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java
index 850556e32d..cafe000601 100644
--- a/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java
+++ b/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java
@@ -22,6 +22,7 @@
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.interceptor.PreResultListener;
import com.opensymphony.xwork2.util.TextParseUtil;
+import org.apache.struts2.RequestUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -58,7 +59,7 @@ public String intercept(ActionInvocation invocation) throws Exception {
@Override
public void beforeResult(ActionInvocation invocation, String resultCode) {
HttpServletRequest req = invocation.getInvocationContext().getServletRequest();
- final String path = req.getContextPath();
+ final String path = RequestUtils.getUri(req);
if (exemptedPaths.contains(path)) {
// no need to add headers
diff --git a/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java
index 123170baff..209db33e2b 100644
--- a/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java
+++ b/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java
@@ -22,6 +22,7 @@
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.interceptor.PreResultListener;
import com.opensymphony.xwork2.util.TextParseUtil;
+import org.apache.struts2.RequestUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -60,7 +61,7 @@ public String intercept(ActionInvocation invocation) throws Exception {
@Override
public void beforeResult(ActionInvocation invocation, String resultCode) {
HttpServletRequest request = invocation.getInvocationContext().getServletRequest();
- String path = request.getContextPath();
+ String path = RequestUtils.getUri(request);
if (isExempted(path)) {
// no need to add headers
diff --git a/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java
index 0f46206f2c..17d7cbbdaa 100644
--- a/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java
+++ b/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java
@@ -23,6 +23,7 @@
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.util.TextParseUtil;
+import org.apache.struts2.RequestUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -67,9 +68,9 @@ public String intercept(ActionInvocation invocation) throws Exception {
addVaryHeaders(invocation);
- String contextPath = request.getContextPath();
+ String path = RequestUtils.getUri(request);
// Apply exemptions: paths/endpoints meant to be served cross-origin
- if (exemptedPaths.contains(contextPath)) {
+ if (exemptedPaths.contains(path)) {
return invocation.invoke();
}
@@ -78,7 +79,7 @@ public String intercept(ActionInvocation invocation) throws Exception {
return invocation.invoke();
}
- LOG.warn("Fetch metadata rejected cross-origin request to: {}", contextPath);
+ LOG.warn("Fetch metadata rejected cross-origin request to: {}", path);
return SC_FORBIDDEN;
}
diff --git a/core/src/test/java/org/apache/struts2/interceptor/CoepInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/CoepInterceptorTest.java
index 72ea1a024c..83392d6bf5 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/CoepInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/CoepInterceptorTest.java
@@ -52,7 +52,19 @@ public void testEnforcingHeader() throws Exception {
}
public void testExemptedPath() throws Exception{
- request.setContextPath("/foo");
+ request.setServletPath("/foo");
+ interceptor.setEnforcingMode("true");
+
+ interceptor.intercept(mai);
+
+ String header = response.getHeader(COEP_ENFORCING_HEADER);
+ assertTrue("COEP applied to exempted path", Strings.isEmpty(header));
+ }
+
+ public void testExemptedPathInfo() throws Exception {
+ interceptor.setExemptedPaths("/rest/orders");
+ request.setServletPath("/rest");
+ request.setPathInfo("/orders");
interceptor.setEnforcingMode("true");
interceptor.intercept(mai);
@@ -61,6 +73,16 @@ public void testExemptedPath() throws Exception{
assertTrue("COEP applied to exempted path", Strings.isEmpty(header));
}
+ public void testHeaderSetWhenOnlyContextPathIsExempted() throws Exception {
+ request.setContextPath("/foo");
+ request.setServletPath("/index.action");
+ interceptor.setEnforcingMode("true");
+
+ interceptor.intercept(mai);
+
+ assertEquals("COEP header value is incorrect", HEADER_CONTENT, response.getHeader(COEP_ENFORCING_HEADER));
+ }
+
public void testReportingHeader() throws Exception {
interceptor.setEnforcingMode("false");
diff --git a/core/src/test/java/org/apache/struts2/interceptor/CoopInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/CoopInterceptorTest.java
index 544e7b5d88..b9e7aac0c8 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/CoopInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/CoopInterceptorTest.java
@@ -38,7 +38,7 @@ public class CoopInterceptorTest extends StrutsInternalTestCase {
String COOP_HEADER = "Cross-Origin-Opener-Policy";
public void testHeaderIsSetNonExemptedPath() throws Exception {
- request.setContextPath("/some");
+ request.setServletPath("/some.action");
interceptor.intercept(mai);
String header = response.getHeader(COOP_HEADER);
@@ -47,16 +47,34 @@ public void testHeaderIsSetNonExemptedPath() throws Exception {
}
public void testHeaderIsNotSetExemptedPath() throws Exception {
- request.setContextPath("/foo");
+ request.setServletPath("/foo");
+ interceptor.intercept(mai);
+
+ String header = response.getHeader(COOP_HEADER);
+ assertTrue("Coop header exists in exempted path", Strings.isEmpty(header));
+ }
+
+ public void testHeaderIsNotSetExemptedPathInfo() throws Exception {
+ interceptor.setExemptedPaths("/rest/orders");
+ request.setServletPath("/rest");
+ request.setPathInfo("/orders");
interceptor.intercept(mai);
String header = response.getHeader(COOP_HEADER);
assertTrue("Coop header exists in exempted path", Strings.isEmpty(header));
}
+ public void testHeaderIsSetWhenOnlyContextPathIsExempted() throws Exception {
+ request.setContextPath("/foo");
+ request.setServletPath("/index.action");
+ interceptor.intercept(mai);
+
+ assertEquals("Coop header is not same-origin", SAME_ORIGIN, response.getHeader(COOP_HEADER));
+ }
+
public void testChangeDefaultMode() throws Exception {
interceptor.setMode("unsafe-none");
- request.setContextPath("/some");
+ request.setServletPath("/some.action");
interceptor.intercept(mai);
String header = response.getHeader(COOP_HEADER);
@@ -65,7 +83,7 @@ public void testChangeDefaultMode() throws Exception {
}
public void testErrorNotRecognizedMode() {
- request.setContextPath("/some");
+ request.setServletPath("/some.action");
try{
interceptor.setMode("foobar");
diff --git a/core/src/test/java/org/apache/struts2/interceptor/FetchMetadataInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/FetchMetadataInterceptorTest.java
index 9b52c94dfd..189472aa77 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/FetchMetadataInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/FetchMetadataInterceptorTest.java
@@ -33,6 +33,7 @@
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
+import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Collection;
@@ -150,21 +151,46 @@ public void testInvalidTopLevelNavigation() throws Exception {
public void testPathInExemptedPaths() throws Exception {
request.addHeader(SEC_FETCH_SITE_HEADER, "foo");
- request.setContextPath("/foo");
+ request.setServletPath("/foo");
assertNotEquals("Expected interceptor to accept this request", SC_FORBIDDEN, interceptor.intercept(mai));
}
public void testPathNotInExemptedPaths() throws Exception {
request.addHeader(SEC_FETCH_SITE_HEADER, "foo");
- request.setContextPath("/foobar");
+ request.setServletPath("/foobar");
+
+ assertEquals("Expected interceptor to NOT accept this request", SC_FORBIDDEN, interceptor.intercept(mai));
+ }
+
+ public void testPathInfoInExemptedPaths() throws Exception {
+ interceptor.setExemptedPaths("/rest/orders");
+ request.addHeader(SEC_FETCH_SITE_HEADER, SITE_CROSS_SITE);
+ request.setServletPath("/rest");
+ request.setPathInfo("/orders");
+
+ assertNotEquals("Expected interceptor to accept this request", SC_FORBIDDEN, interceptor.intercept(mai));
+ }
+
+ public void testContextPathInExemptedPathsDoesNotExempt() throws Exception {
+ request.addHeader(SEC_FETCH_SITE_HEADER, SITE_CROSS_SITE);
+ request.setContextPath("/foo");
+ request.setServletPath("/index.action");
assertEquals("Expected interceptor to NOT accept this request", SC_FORBIDDEN, interceptor.intercept(mai));
}
+ public void testIncludedPathInExemptedPaths() throws Exception {
+ request.addHeader(SEC_FETCH_SITE_HEADER, SITE_CROSS_SITE);
+ request.setServletPath("/outer.action");
+ request.setAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH, "/foo");
+
+ assertNotEquals("Expected interceptor to accept this request", SC_FORBIDDEN, interceptor.intercept(mai));
+ }
+
public void testVaryHeaderAcceptedReq() throws Exception {
request.addHeader(SEC_FETCH_SITE_HEADER, "foo");
- request.setContextPath("/foo");
+ request.setServletPath("/foo");
interceptor.intercept(mai);
@@ -222,11 +248,11 @@ public void testSetExemptedPathsInjectionIndirectly() throws Exception {
FetchMetadataInterceptor configuredFetchMetadataInterceptor = (FetchMetadataInterceptor) configuredFetchMetadataInterceptorMapping.getInterceptor();
request.removeHeader(SEC_FETCH_SITE_HEADER);
request.addHeader(SEC_FETCH_SITE_HEADER, "foo");
- request.setContextPath("/foo");
+ request.setServletPath("/foo");
assertEquals("Expected interceptor to NOT accept this request [/foo]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai));
- request.setContextPath("/fetchMetadataExemptedGlobal");
+ request.setServletPath("/fetchMetadataExemptedGlobal.action");
assertNotEquals("Expected interceptor to accept this request [/fetchMetadataExemptedGlobal]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai));
- request.setContextPath("/someOtherPath");
+ request.setServletPath("/someOtherPath.action");
assertNotEquals("Expected interceptor to accept this request [/someOtherPath]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai));
// The test configuration in "struts-testing.xml" should also contain three actions configured differently for the "fetchMetadata" interceptor.
@@ -257,8 +283,8 @@ public void testSetExemptedPathsInjectionIndirectly() throws Exception {
configuredFetchMetadataInterceptor = (FetchMetadataInterceptor) configuredFetchMetadataInterceptorMapping.getInterceptor();
request.removeHeader(SEC_FETCH_SITE_HEADER);
request.addHeader(SEC_FETCH_SITE_HEADER, fetchMetadataExemptedActionConfig.getName());
- request.setContextPath("/" + fetchMetadataExemptedActionConfig.getName());
- assertNotEquals("Expected interceptor to accept this request [" + "/" + fetchMetadataExemptedActionConfig.getName() + "]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai));
+ request.setServletPath("/" + fetchMetadataExemptedActionConfig.getName() + ".action");
+ assertNotEquals("Expected interceptor to accept this request [" + "/" + fetchMetadataExemptedActionConfig.getName() + ".action" + "]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai));
// Test fetchMetadata interceptor for the "fetchMetadataNotExempted" action.
currentActionInterceptors = fetchMetadataNotExemptedActionConfig.getInterceptors();
@@ -277,8 +303,8 @@ public void testSetExemptedPathsInjectionIndirectly() throws Exception {
configuredFetchMetadataInterceptor = (FetchMetadataInterceptor) configuredFetchMetadataInterceptorMapping.getInterceptor();
request.removeHeader(SEC_FETCH_SITE_HEADER);
request.addHeader(SEC_FETCH_SITE_HEADER, fetchMetadataNotExemptedActionConfig.getName());
- request.setContextPath("/" + fetchMetadataNotExemptedActionConfig.getName());
- assertEquals("Expected interceptor to NOT accept this request [" + "/" + fetchMetadataNotExemptedActionConfig.getName() + "]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai));
+ request.setServletPath("/" + fetchMetadataNotExemptedActionConfig.getName() + ".action");
+ assertEquals("Expected interceptor to NOT accept this request [" + "/" + fetchMetadataNotExemptedActionConfig.getName() + ".action" + "]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai));
// Test fetchMetadata interceptor for the "fetchMetadataExemptedGlobal" action.
currentActionInterceptors = fetchMetadataExemptedGlobalActionConfig.getInterceptors();
@@ -297,8 +323,8 @@ public void testSetExemptedPathsInjectionIndirectly() throws Exception {
configuredFetchMetadataInterceptor = (FetchMetadataInterceptor) configuredFetchMetadataInterceptorMapping.getInterceptor();
request.removeHeader(SEC_FETCH_SITE_HEADER);
request.addHeader(SEC_FETCH_SITE_HEADER, fetchMetadataExemptedGlobalActionConfig.getName());
- request.setContextPath("/" + fetchMetadataExemptedGlobalActionConfig.getName());
- assertNotEquals("Expected interceptor to accept this request [" + "/" + fetchMetadataExemptedGlobalActionConfig.getName() + "]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai));
+ request.setServletPath("/" + fetchMetadataExemptedGlobalActionConfig.getName() + ".action");
+ assertNotEquals("Expected interceptor to accept this request [" + "/" + fetchMetadataExemptedGlobalActionConfig.getName() + ".action" + "]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai));
}
}
diff --git a/core/src/test/resources/struts-testing.xml b/core/src/test/resources/struts-testing.xml
index f1af997ce6..a73c2c5b64 100644
--- a/core/src/test/resources/struts-testing.xml
+++ b/core/src/test/resources/struts-testing.xml
@@ -28,21 +28,21 @@
- /fetchMetadataExemptedGlobal,/someOtherPath
+ /fetchMetadataExemptedGlobal.action,/someOtherPath.action
- /fetchMetadataExempted
+ /fetchMetadataExempted.action
hello.jsp
- /nonMatchingActionPath
+ /nonMatchingActionPath.action
hello.jsp