This is an automated email from the ASF dual-hosted git repository. lukaszlenart pushed a commit to branch fix/WW-5368-invalid-session in repository https://gitbox.apache.org/repos/asf/struts.git
commit 9b347f6b4e7115ec6f90b1896b08829e9364fb84 Author: Lukasz Lenart <lukaszlen...@apache.org> AuthorDate: Mon Sep 23 19:56:43 2024 +0200 WW-5368 Fixes checking nonce of invalidated session --- .../java/org/apache/struts2/components/UIBean.java | 8 +++- .../org/apache/struts2/components/UIBeanTest.java | 43 +++++++++++++++++++--- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/org/apache/struts2/components/UIBean.java b/core/src/main/java/org/apache/struts2/components/UIBean.java index 59d3713ed..c787fd100 100644 --- a/core/src/main/java/org/apache/struts2/components/UIBean.java +++ b/core/src/main/java/org/apache/struts2/components/UIBean.java @@ -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(); diff --git a/core/src/test/java/org/apache/struts2/components/UIBeanTest.java b/core/src/test/java/org/apache/struts2/components/UIBeanTest.java index 690328942..1bff06889 100644 --- a/core/src/test/java/org/apache/struts2/components/UIBeanTest.java +++ b/core/src/test/java/org/apache/struts2/components/UIBeanTest.java @@ -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();