WW-5297 Fixes checking nonce of invalidated session

This commit is contained in:
Lukasz Lenart
2024-09-23 19:58:06 +02:00
parent 48c4e3b6a0
commit 0bd4266d2f
6 changed files with 59 additions and 35 deletions
@@ -40,6 +40,7 @@ import org.apache.struts2.views.util.ContextUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.Writer;
import java.util.HashMap;
import java.util.LinkedHashMap;
@@ -863,10 +864,13 @@ public abstract class UIBean extends Component {
}
// to be used with the CSP interceptor - adds the nonce value as a parameter to be accessed from ftl files
Map<String, Object> session = stack.getActionContext().getSession();
Object nonceValue = session != null ? session.get("nonce") : null;
HttpSession session = stack.getActionContext().getServletRequest().getSession(false);
Object nonceValue = session != null ? session.getAttribute("nonce") : null;
if (nonceValue != null) {
addParameter("nonce", nonceValue.toString());
} else {
LOG.debug("Session is not active, cannot obtain nonce value");
}
evaluateExtraParams();
@@ -25,12 +25,13 @@ import org.apache.struts2.StrutsInternalTestCase;
import org.apache.struts2.components.template.Template;
import org.apache.struts2.components.template.TemplateEngine;
import org.apache.struts2.components.template.TemplateEngineManager;
import org.apache.struts2.dispatcher.SessionMap;
import org.apache.struts2.dispatcher.StaticContentLoader;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockHttpSession;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static com.opensymphony.xwork2.security.DefaultNotExcludedAcceptedPatternsCheckerTest.NO_EXCLUSION_ACCEPT_ALL_PATTERNS_CHECKER;
@@ -160,7 +161,7 @@ public class UIBeanTest extends StrutsInternalTestCase {
try {
txtFld.mergeTemplate(null, new Template(null, null, null));
fail("Exception not thrown");
} catch(final Exception e){
} catch (final Exception e) {
assertTrue(e instanceof ConfigurationException);
}
}
@@ -225,6 +226,7 @@ public class UIBeanTest extends StrutsInternalTestCase {
ValueStack stack = ActionContext.getContext().getValueStack();
MockHttpServletRequest req = new MockHttpServletRequest();
MockHttpServletResponse res = new MockHttpServletResponse();
ActionContext.getContext().withServletRequest(req);
TextField txtFld = new TextField(stack, req, res);
txtFld.setAccesskey(accesskeyValue);
@@ -238,6 +240,7 @@ public class UIBeanTest extends StrutsInternalTestCase {
ValueStack stack = ActionContext.getContext().getValueStack();
MockHttpServletRequest req = new MockHttpServletRequest();
MockHttpServletResponse res = new MockHttpServletResponse();
ActionContext.getContext().withServletRequest(req);
TextField txtFld = new TextField(stack, req, res);
txtFld.addParameter("value", value);
@@ -250,11 +253,13 @@ public class UIBeanTest extends StrutsInternalTestCase {
ValueStack stack = ActionContext.getContext().getValueStack();
MockHttpServletRequest req = new MockHttpServletRequest();
MockHttpServletResponse res = new MockHttpServletResponse();
ActionContext.getContext().withServletRequest(req);
stack.push(new Object() {
public String getMyValue() {
return "%{myBad}";
}
public String getMyBad() {
throw new IllegalStateException("Recursion detected!");
}
@@ -273,11 +278,13 @@ public class UIBeanTest extends StrutsInternalTestCase {
ValueStack stack = ActionContext.getContext().getValueStack();
MockHttpServletRequest req = new MockHttpServletRequest();
MockHttpServletResponse res = new MockHttpServletResponse();
ActionContext.getContext().withServletRequest(req);
stack.push(new Object() {
public String getMyValueName() {
return "getMyValue()";
}
public String getMyValue() {
return "value";
}
@@ -300,6 +307,7 @@ public class UIBeanTest extends StrutsInternalTestCase {
ValueStack stack = ActionContext.getContext().getValueStack();
MockHttpServletRequest req = new MockHttpServletRequest();
MockHttpServletResponse res = new MockHttpServletResponse();
ActionContext.getContext().withServletRequest(req);
stack.push(new Object() {
public String getMyValue() {
@@ -320,6 +328,7 @@ public class UIBeanTest extends StrutsInternalTestCase {
ValueStack stack = ActionContext.getContext().getValueStack();
MockHttpServletRequest req = new MockHttpServletRequest();
MockHttpServletResponse res = new MockHttpServletResponse();
ActionContext.getContext().withServletRequest(req);
TextField txtFld = new TextField(stack, req, res);
txtFld.setCssClass(cssClass);
@@ -333,6 +342,7 @@ public class UIBeanTest extends StrutsInternalTestCase {
ValueStack stack = ActionContext.getContext().getValueStack();
MockHttpServletRequest req = new MockHttpServletRequest();
MockHttpServletResponse res = new MockHttpServletResponse();
ActionContext.getContext().withServletRequest(req);
TextField txtFld = new TextField(stack, req, res);
txtFld.setStyle(cssStyle);
@@ -347,9 +357,12 @@ public class UIBeanTest extends StrutsInternalTestCase {
MockHttpServletRequest req = new MockHttpServletRequest();
MockHttpServletResponse res = new MockHttpServletResponse();
ActionContext actionContext = stack.getActionContext();
Map<String, Object> session = new HashMap<>();
session.put("nonce", nonceVal);
actionContext.withSession(session);
actionContext.withServletRequest(req);
MockHttpSession session = new MockHttpSession();
session.putValue("nonce", nonceVal);
req.setSession(session);
actionContext.withSession(new SessionMap(req));
DoubleSelect dblSelect = new DoubleSelect(stack, req, res);
dblSelect.evaluateParams();
@@ -357,6 +370,26 @@ public class UIBeanTest extends StrutsInternalTestCase {
assertEquals(nonceVal, dblSelect.getParameters().get("nonce"));
}
public void testNonceOfInvalidSession() {
String nonceVal = "r4nd0m";
ValueStack stack = ActionContext.getContext().getValueStack();
MockHttpServletRequest req = new MockHttpServletRequest();
MockHttpServletResponse res = new MockHttpServletResponse();
ActionContext actionContext = stack.getActionContext();
actionContext.withServletRequest(req);
MockHttpSession session = new MockHttpSession();
session.putValue("nonce", nonceVal);
req.setSession(session);
actionContext.withSession(new SessionMap(req));
session.invalidate();
DoubleSelect dblSelect = new DoubleSelect(stack, req, res);
dblSelect.evaluateParams();
assertNull(dblSelect.getParameters().get("nonce"));
}
public void testSetNullUiStaticContentPath() {
// given
ValueStack stack = ActionContext.getContext().getValueStack();
@@ -35,6 +35,7 @@ import org.apache.struts2.components.template.TemplateRenderingContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
@@ -51,6 +52,8 @@ public abstract class AbstractTest extends TestCase {
private final Map<String, String> commonAttrs = new HashMap<>();
private final Map<String, String> dynamicAttrs = new HashMap<>();
protected static final String NONCE_VAL = "r4andom";
protected SimpleTheme theme;
protected StringWriter writer;
@@ -62,6 +65,7 @@ public abstract class AbstractTest extends TestCase {
protected TemplateRenderingContext context;
protected HttpServletRequest request;
protected HttpServletResponse response;
private HttpSession session;
protected abstract UIBean getUIBean() throws Exception;
@@ -107,6 +111,12 @@ public abstract class AbstractTest extends TestCase {
expect(request.getContextPath()).andReturn("/some/path").anyTimes();
response = createNiceMock(HttpServletResponse.class);
session = createNiceMock(HttpSession.class);
expect(session.getAttribute("nonce")).andReturn(NONCE_VAL).anyTimes();
expect(request.getSession(false)).andReturn(session).anyTimes();
actionContext.withServletRequest(request);
expect(stack.getActionContext()).andReturn(actionContext).anyTimes();
expect(stack.getContext()).andReturn(stackContext).anyTimes();
@@ -116,6 +126,7 @@ public abstract class AbstractTest extends TestCase {
TextParser parser = new OgnlTextParser();
expect(container.getInstance(TextParser.class)).andReturn(parser).anyTimes();
replay(session);
replay(request);
replay(stack);
replay(container);
@@ -31,7 +31,7 @@ public class HeadTest extends AbstractTest {
map.putAll(tag.getParameters());
theme.renderTag(getTagName(), context);
String output = writer.getBuffer().toString();
String expected = s("<script type='text/javascript' base='/some/path' src='/some/path/static/utils.js'></script>");
String expected = s("<script type='text/javascript' base='/some/path' src='/some/path/static/utils.js' nonce='r4andom'></script>");
assertEquals(expected, output);
}
@@ -18,19 +18,13 @@
*/
package org.apache.struts2.views.java.simple;
import com.opensymphony.xwork2.ActionContext;
import org.apache.struts2.components.Link;
import org.apache.struts2.components.UIBean;
import java.util.HashMap;
import java.util.Map;
public class LinkTest extends AbstractTest{
public class LinkTest extends AbstractTest {
private Link tag;
private static final String NONCE_VAL = "r4andom";
public void testRenderLinkTag() {
tag.setHref("testhref");
tag.setHreflang("test");
@@ -60,7 +54,7 @@ public class LinkTest extends AbstractTest{
assertTrue("Incorrect as attribute for link tag", output.contains(s("as='test'")));
assertFalse("Non-existent disabled attribute for link tag", output.contains(s("disabled='disabled'")));
assertTrue("Incorrect title attribute for link tag", output.contains(s("title='test'")));
assertTrue("Incorrect nonce attribute for link tag", output.contains(s("nonce='" + NONCE_VAL+"'")));
assertTrue("Incorrect nonce attribute for link tag", output.contains(s("nonce='" + NONCE_VAL + "'")));
}
public void testRenderLinkTagAsStylesheet() {
@@ -92,7 +86,7 @@ public class LinkTest extends AbstractTest{
assertTrue("Incorrect as attribute for link tag", output.contains(s("as='test'")));
assertTrue("Incorrect disabled attribute for link tag", output.contains(s("disabled='disabled'")));
assertTrue("Incorrect title attribute for link tag", output.contains(s("title='test'")));
assertTrue("Incorrect nonce attribute for link tag", output.contains(s("nonce='" + NONCE_VAL+"'")));
assertTrue("Incorrect nonce attribute for link tag", output.contains(s("nonce='" + NONCE_VAL + "'")));
}
@Override
@@ -108,12 +102,6 @@ public class LinkTest extends AbstractTest{
@Override
protected void setUp() throws Exception {
super.setUp();
ActionContext actionContext = stack.getActionContext();
Map<String, Object> session = new HashMap<>();
session.put("nonce", NONCE_VAL);
actionContext.withSession(session);
this.tag = new Link(stack, request, response);
}
}
@@ -18,22 +18,15 @@
*/
package org.apache.struts2.views.java.simple;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.security.DefaultNotExcludedAcceptedPatternsChecker;
import org.apache.struts2.components.Script;
import org.apache.struts2.components.UIBean;
import java.util.HashMap;
import java.util.Map;
public class ScriptTest extends AbstractTest {
private Script tag;
private static final String NONCE_VAL = "r4andom";
public void testRenderScriptTag() {
tag.setName("name_");
tag.setType("text/javascript");
@@ -77,11 +70,6 @@ public class ScriptTest extends AbstractTest {
protected void setUp() throws Exception {
super.setUp();
ActionContext actionContext = stack.getActionContext();
Map<String, Object> session = new HashMap<>();
session.put("nonce", NONCE_VAL);
actionContext.withSession(session);
this.tag = new Script(stack, request, response);
tag.setNotExcludedAcceptedPatterns(new DefaultNotExcludedAcceptedPatternsChecker());
}