mirror of
https://github.com/apache/struts.git
synced 2026-08-05 06:36:58 +00:00
WW-5504 Allows to use request instead of session attribute to store nonce (#1352)
This commit is contained in:
@@ -673,4 +673,11 @@ public final class StrutsConstants {
|
||||
* See {@link org.apache.struts2.interceptor.exec.ExecutorProvider}
|
||||
*/
|
||||
public static final String STRUTS_EXECUTOR_PROVIDER = "struts.executor.provider";
|
||||
|
||||
/**
|
||||
* See {@link org.apache.struts2.interceptor.csp.CspNonceReader}
|
||||
* @since 6.8.0
|
||||
*/
|
||||
public static final String STRUTS_CSP_NONCE_READER = "struts.csp.nonce.reader";
|
||||
public static final String STRUTS_CSP_NONCE_SOURCE = "struts.csp.nonce.source";
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.apache.struts2.components.template.TemplateEngineManager;
|
||||
import org.apache.struts2.components.template.TemplateRenderingContext;
|
||||
import org.apache.struts2.dispatcher.AttributeMap;
|
||||
import org.apache.struts2.dispatcher.StaticContentLoader;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceReader;
|
||||
import org.apache.struts2.util.ComponentUtils;
|
||||
import org.apache.struts2.util.TextProviderHelper;
|
||||
import org.apache.struts2.views.annotations.StrutsTagAttribute;
|
||||
@@ -528,6 +529,8 @@ public abstract class UIBean extends Component {
|
||||
|
||||
protected TemplateEngineManager templateEngineManager;
|
||||
|
||||
protected CspNonceReader cspNonceReader;
|
||||
|
||||
@Inject(StrutsConstants.STRUTS_UI_TEMPLATEDIR)
|
||||
public void setDefaultTemplateDir(String dir) {
|
||||
this.defaultTemplateDir = dir;
|
||||
@@ -553,6 +556,11 @@ public abstract class UIBean extends Component {
|
||||
this.templateEngineManager = mgr;
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setCspNonceReader(CspNonceReader cspNonceReader) {
|
||||
this.cspNonceReader = cspNonceReader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean end(Writer writer, String body) {
|
||||
evaluateParams();
|
||||
@@ -886,13 +894,12 @@ 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
|
||||
HttpSession session = stack.getActionContext().getServletRequest().getSession(false);
|
||||
Object nonceValue = session != null ? session.getAttribute("nonce") : null;
|
||||
CspNonceReader.NonceValue nonceValue = cspNonceReader.readNonceValue(stack);
|
||||
|
||||
if (nonceValue != null) {
|
||||
addParameter("nonce", nonceValue.toString());
|
||||
if (nonceValue.isNonceValueSet()) {
|
||||
addParameter("nonce", nonceValue.getNonceValue());
|
||||
} else {
|
||||
LOG.debug("Session is not active, cannot obtain nonce value");
|
||||
LOG.debug("Nonce not defined in: {}", nonceValue.getSource());
|
||||
}
|
||||
|
||||
evaluateExtraParams();
|
||||
|
||||
@@ -55,6 +55,7 @@ import org.apache.struts2.factory.UnknownHandlerFactory;
|
||||
import org.apache.struts2.factory.ValidatorFactory;
|
||||
import org.apache.struts2.inject.ContainerBuilder;
|
||||
import org.apache.struts2.inject.Scope;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceReader;
|
||||
import org.apache.struts2.interceptor.exec.ExecutorProvider;
|
||||
import org.apache.struts2.ognl.BeanInfoCacheFactory;
|
||||
import org.apache.struts2.ognl.ExpressionCacheFactory;
|
||||
@@ -450,6 +451,8 @@ public class StrutsBeanSelectionProvider extends AbstractBeanSelectionProvider {
|
||||
|
||||
alias(ExecutorProvider.class, StrutsConstants.STRUTS_EXECUTOR_PROVIDER, builder, props, Scope.SINGLETON);
|
||||
|
||||
alias(CspNonceReader.class, StrutsConstants.STRUTS_CSP_NONCE_READER, builder, props, Scope.SINGLETON);
|
||||
|
||||
switchDevMode(props);
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -68,6 +68,8 @@ import org.apache.struts2.validator.ValidatorFileParser;
|
||||
import ognl.PropertyAccessor;
|
||||
import org.apache.struts2.dispatcher.HttpParameters;
|
||||
import org.apache.struts2.dispatcher.Parameter;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceReader;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
import org.apache.struts2.interceptor.exec.ExecutorProvider;
|
||||
import org.apache.struts2.interceptor.exec.StrutsExecutorProvider;
|
||||
import org.apache.struts2.url.QueryStringBuilder;
|
||||
@@ -159,7 +161,9 @@ public class StrutsDefaultConfigurationProvider implements ConfigurationProvider
|
||||
.factory(UrlEncoder.class, StrutsUrlEncoder.class, Scope.SINGLETON)
|
||||
.factory(UrlDecoder.class, StrutsUrlDecoder.class, Scope.SINGLETON)
|
||||
|
||||
.factory(ExecutorProvider.class, StrutsExecutorProvider.class, Scope.SINGLETON);
|
||||
.factory(ExecutorProvider.class, StrutsExecutorProvider.class, Scope.SINGLETON)
|
||||
|
||||
.factory(CspNonceReader.class, StrutsCspNonceReader.class, Scope.SINGLETON);
|
||||
|
||||
for (Map.Entry<String, Object> entry : DefaultConfiguration.BOOTSTRAP_CONSTANTS.entrySet()) {
|
||||
props.setProperty(entry.getKey(), String.valueOf(entry.getValue()));
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.interceptor.csp;
|
||||
|
||||
import org.apache.struts2.util.ValueStack;
|
||||
|
||||
/**
|
||||
* Reads the nonce value using the ValueStack, {@link StrutsCspNonceReader} is the default implementation
|
||||
* @since 6.8.0
|
||||
*/
|
||||
public interface CspNonceReader {
|
||||
|
||||
NonceValue readNonceValue(ValueStack stack);
|
||||
|
||||
class NonceValue {
|
||||
private final String nonceValue;
|
||||
private final CspNonceSource source;
|
||||
|
||||
private NonceValue(String nonceValue, CspNonceSource source) {
|
||||
this.nonceValue = nonceValue;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public static NonceValue ofSession(String nonceValue) {
|
||||
return new NonceValue(nonceValue, CspNonceSource.SESSION);
|
||||
}
|
||||
|
||||
public static NonceValue ofRequest(String nonceValue) {
|
||||
return new NonceValue(nonceValue, CspNonceSource.REQUEST);
|
||||
}
|
||||
|
||||
public static NonceValue ofNullSession() {
|
||||
return new NonceValue(null, CspNonceSource.SESSION);
|
||||
}
|
||||
|
||||
public static NonceValue ofNullRequest() {
|
||||
return new NonceValue(null, CspNonceSource.REQUEST);
|
||||
}
|
||||
|
||||
public boolean isNonceValueSet() {
|
||||
return nonceValue != null;
|
||||
}
|
||||
|
||||
public String getNonceValue() {
|
||||
return nonceValue;
|
||||
}
|
||||
|
||||
public CspNonceSource getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String displayNonce;
|
||||
if (nonceValue != null && nonceValue.length() >= 4) {
|
||||
displayNonce = String.format("nonceValue='%s**********'", nonceValue.substring(0, 4));
|
||||
} else if (nonceValue != null) {
|
||||
displayNonce = String.format("nonceValue='%s**********'", nonceValue);
|
||||
} else {
|
||||
displayNonce = "nonceValue='<null>'";
|
||||
}
|
||||
return "NonceValue{" +
|
||||
displayNonce +
|
||||
", source=" + source +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.interceptor.csp;
|
||||
|
||||
/**
|
||||
* Source of the nonce value
|
||||
*/
|
||||
public enum CspNonceSource {
|
||||
REQUEST,
|
||||
SESSION
|
||||
}
|
||||
@@ -20,13 +20,15 @@ package org.apache.struts2.interceptor.csp;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.struts2.inject.Inject;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.action.CspSettingsAware;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Base64;
|
||||
import java.util.Objects;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
@@ -43,63 +45,86 @@ import static java.lang.String.format;
|
||||
*/
|
||||
public class DefaultCspSettings implements CspSettings {
|
||||
|
||||
private final static Logger LOG = LogManager.getLogger(DefaultCspSettings.class);
|
||||
private static final Logger LOG = LogManager.getLogger(DefaultCspSettings.class);
|
||||
private static final String NONCE_KEY = "nonce";
|
||||
|
||||
private final SecureRandom sRand = new SecureRandom();
|
||||
|
||||
private CspNonceSource nonceSource = CspNonceSource.SESSION;
|
||||
|
||||
protected String reportUri;
|
||||
protected String reportTo;
|
||||
// default to reporting mode
|
||||
protected String cspHeader = CSP_REPORT_HEADER;
|
||||
|
||||
@Inject(value = StrutsConstants.STRUTS_CSP_NONCE_SOURCE, required = false)
|
||||
public void setNonceSource(String nonceSource) {
|
||||
if (StringUtils.isBlank(nonceSource)) {
|
||||
this.nonceSource = CspNonceSource.SESSION;
|
||||
} else {
|
||||
this.nonceSource = CspNonceSource.valueOf(nonceSource.toUpperCase());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCspHeaders(HttpServletRequest request, HttpServletResponse response) {
|
||||
if (this.nonceSource == CspNonceSource.SESSION) {
|
||||
addCspHeadersWithSession(request, response);
|
||||
} else if (this.nonceSource == CspNonceSource.REQUEST) {
|
||||
addCspHeadersWithRequest(request, response);
|
||||
} else {
|
||||
LOG.warn("Unknown nonce source: {}, ignoring CSP settings", nonceSource);
|
||||
}
|
||||
}
|
||||
|
||||
private void addCspHeadersWithSession(HttpServletRequest request, HttpServletResponse response) {
|
||||
if (isSessionActive(request)) {
|
||||
LOG.trace("Session is active, applying CSP settings");
|
||||
associateNonceWithSession(request);
|
||||
response.setHeader(cspHeader, createPolicyFormat(request));
|
||||
String nonceValue = generateNonceValue();
|
||||
request.getSession().setAttribute(NONCE_KEY, nonceValue);
|
||||
response.setHeader(cspHeader, createPolicyFormat(nonceValue));
|
||||
} else {
|
||||
LOG.trace("Session is not active, ignoring CSP settings");
|
||||
LOG.debug("Session is not active, ignoring CSP settings");
|
||||
}
|
||||
}
|
||||
|
||||
private void addCspHeadersWithRequest(HttpServletRequest request, HttpServletResponse response) {
|
||||
String nonceValue = generateNonceValue();
|
||||
request.setAttribute(NONCE_KEY, nonceValue);
|
||||
response.setHeader(cspHeader, createPolicyFormat(nonceValue));
|
||||
}
|
||||
|
||||
private boolean isSessionActive(HttpServletRequest request) {
|
||||
return request.getSession(false) != null;
|
||||
}
|
||||
|
||||
private void associateNonceWithSession(HttpServletRequest request) {
|
||||
String nonceValue = Base64.getUrlEncoder().encodeToString(getRandomBytes());
|
||||
request.getSession().setAttribute("nonce", nonceValue);
|
||||
private String generateNonceValue() {
|
||||
return Base64.getUrlEncoder().encodeToString(getRandomBytes());
|
||||
}
|
||||
|
||||
protected String createPolicyFormat(HttpServletRequest request) {
|
||||
StringBuilder policyFormatBuilder = new StringBuilder()
|
||||
.append(OBJECT_SRC)
|
||||
.append(format(" '%s'; ", NONE))
|
||||
.append(SCRIPT_SRC)
|
||||
.append(" 'nonce-%s' ") // nonce placeholder
|
||||
.append(format("'%s' ", STRICT_DYNAMIC))
|
||||
.append(format("%s %s; ", HTTP, HTTPS))
|
||||
.append(BASE_URI)
|
||||
.append(format(" '%s'; ", NONE));
|
||||
protected String createPolicyFormat(String nonceValue) {
|
||||
StringBuilder builder = new StringBuilder()
|
||||
.append(OBJECT_SRC)
|
||||
.append(format(" '%s'; ", NONE))
|
||||
.append(SCRIPT_SRC)
|
||||
.append(format(" 'nonce-%s' ", nonceValue))
|
||||
.append(format("'%s' ", STRICT_DYNAMIC))
|
||||
.append(format("%s %s; ", HTTP, HTTPS))
|
||||
.append(BASE_URI)
|
||||
.append(format(" '%s'; ", NONE));
|
||||
|
||||
if (reportUri != null) {
|
||||
policyFormatBuilder
|
||||
.append(REPORT_URI)
|
||||
.append(format(" %s; ", reportUri));
|
||||
if(reportTo != null) {
|
||||
policyFormatBuilder
|
||||
builder
|
||||
.append(REPORT_URI)
|
||||
.append(format(" %s; ", reportUri));
|
||||
if (reportTo != null) {
|
||||
builder
|
||||
.append(REPORT_TO)
|
||||
.append(format(" %s; ", reportTo));
|
||||
}
|
||||
}
|
||||
|
||||
return format(policyFormatBuilder.toString(), getNonceString(request));
|
||||
}
|
||||
|
||||
protected String getNonceString(HttpServletRequest request) {
|
||||
Object nonce = request.getSession().getAttribute("nonce");
|
||||
return Objects.toString(nonce);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private byte[] getRandomBytes() {
|
||||
@@ -128,10 +153,10 @@ public class DefaultCspSettings implements CspSettings {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DefaultCspSettings{" +
|
||||
"reportUri='" + reportUri + '\'' +
|
||||
", reportTo='" + reportTo + '\'' +
|
||||
", cspHeader='" + cspHeader + '\'' +
|
||||
'}';
|
||||
"reportUri='" + reportUri + '\'' +
|
||||
", reportTo='" + reportTo + '\'' +
|
||||
", cspHeader='" + cspHeader + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.interceptor.csp;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.inject.Inject;
|
||||
import org.apache.struts2.util.ValueStack;
|
||||
|
||||
/**
|
||||
* Reads nonce value from session or request attribute.
|
||||
* @since 6.8.0
|
||||
*/
|
||||
public class StrutsCspNonceReader implements CspNonceReader {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(StrutsCspNonceReader.class);
|
||||
|
||||
private final CspNonceSource nonceSource;
|
||||
|
||||
@Inject(value = StrutsConstants.STRUTS_CSP_NONCE_SOURCE, required = false)
|
||||
public StrutsCspNonceReader(String source) {
|
||||
if (StringUtils.isBlank(source)) {
|
||||
this.nonceSource = CspNonceSource.SESSION;
|
||||
} else {
|
||||
this.nonceSource = CspNonceSource.valueOf(source.toUpperCase());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public NonceValue readNonceValue(ValueStack stack) {
|
||||
HttpServletRequest request = stack.getActionContext().getServletRequest();
|
||||
NonceValue nonceValue;
|
||||
|
||||
if (nonceSource == CspNonceSource.SESSION) {
|
||||
LOG.debug("Reading nonce value from session");
|
||||
nonceValue = readNonceFromSession(request);
|
||||
} else if (nonceSource == CspNonceSource.REQUEST) {
|
||||
LOG.debug("Reading nonce value from request attribute");
|
||||
nonceValue = readNonceFromRequest(request);
|
||||
} else {
|
||||
LOG.warn("Unknown nonce source: {}, reading nonce value from session", nonceSource);
|
||||
nonceValue = readNonceFromSession(request);
|
||||
}
|
||||
return nonceValue;
|
||||
}
|
||||
|
||||
private NonceValue readNonceFromSession(HttpServletRequest request) {
|
||||
HttpSession session = request.getSession(false);
|
||||
Object nonceValue = session != null ? session.getAttribute("nonce") : null;
|
||||
if (nonceValue == null) {
|
||||
LOG.debug("Session is not active, cannot obtain nonce value");
|
||||
return NonceValue.ofNullSession();
|
||||
}
|
||||
return NonceValue.ofSession(nonceValue.toString());
|
||||
}
|
||||
|
||||
private NonceValue readNonceFromRequest(HttpServletRequest request) {
|
||||
Object nonceValue = request.getAttribute("nonce");
|
||||
if (nonceValue == null) {
|
||||
LOG.warn("Request attribute 'nonce' is not set, cannot obtain nonce value");
|
||||
return NonceValue.ofNullRequest();
|
||||
}
|
||||
|
||||
return NonceValue.ofRequest(nonceValue.toString());
|
||||
}
|
||||
}
|
||||
@@ -299,4 +299,7 @@ struts.url.queryStringParser=strutsQueryStringParser
|
||||
struts.url.encoder=strutsUrlEncoder
|
||||
struts.url.decoder=strutsUrlDecoder
|
||||
|
||||
### Defines source to read nonce value from, possible values are: request, session
|
||||
struts.csp.nonceSource=session
|
||||
|
||||
### END SNIPPET: complete_file
|
||||
|
||||
@@ -250,4 +250,7 @@
|
||||
<bean type="org.apache.struts2.interceptor.exec.ExecutorProvider" name="struts"
|
||||
class="org.apache.struts2.interceptor.exec.StrutsExecutorProvider"/>
|
||||
|
||||
<bean type="org.apache.struts2.interceptor.csp.CspNonceReader" name="struts"
|
||||
class="org.apache.struts2.interceptor.csp.StrutsCspNonceReader"/>
|
||||
|
||||
</struts>
|
||||
|
||||
@@ -21,6 +21,7 @@ package org.apache.struts2.components;
|
||||
import org.apache.struts2.ActionContext;
|
||||
import org.apache.struts2.config.ConfigurationException;
|
||||
import org.apache.struts2.util.ValueStack;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.StrutsInternalTestCase;
|
||||
import org.apache.struts2.components.template.Template;
|
||||
import org.apache.struts2.components.template.TemplateEngine;
|
||||
@@ -32,6 +33,7 @@ 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 org.apache.struts2.security.DefaultNotExcludedAcceptedPatternsCheckerTest.NO_EXCLUSION_ACCEPT_ALL_PATTERNS_CHECKER;
|
||||
@@ -236,6 +238,8 @@ public class UIBeanTest extends StrutsInternalTestCase {
|
||||
ActionContext.getContext().withServletRequest(req);
|
||||
|
||||
TextField txtFld = new TextField(stack, req, res);
|
||||
container.inject(txtFld);
|
||||
|
||||
txtFld.setAccesskey(accesskeyValue);
|
||||
txtFld.evaluateParams();
|
||||
|
||||
@@ -250,6 +254,8 @@ public class UIBeanTest extends StrutsInternalTestCase {
|
||||
ActionContext.getContext().withServletRequest(req);
|
||||
|
||||
TextField txtFld = new TextField(stack, req, res);
|
||||
container.inject(txtFld);
|
||||
|
||||
txtFld.addParameter("value", value);
|
||||
txtFld.evaluateParams();
|
||||
|
||||
@@ -338,6 +344,8 @@ public class UIBeanTest extends StrutsInternalTestCase {
|
||||
ActionContext.getContext().withServletRequest(req);
|
||||
|
||||
TextField txtFld = new TextField(stack, req, res);
|
||||
container.inject(txtFld);
|
||||
|
||||
txtFld.setCssClass(cssClass);
|
||||
txtFld.evaluateParams();
|
||||
|
||||
@@ -352,6 +360,8 @@ public class UIBeanTest extends StrutsInternalTestCase {
|
||||
ActionContext.getContext().withServletRequest(req);
|
||||
|
||||
TextField txtFld = new TextField(stack, req, res);
|
||||
container.inject(txtFld);
|
||||
|
||||
txtFld.setStyle(cssStyle);
|
||||
txtFld.evaluateParams();
|
||||
|
||||
@@ -372,6 +382,8 @@ public class UIBeanTest extends StrutsInternalTestCase {
|
||||
actionContext.withSession(new SessionMap(req));
|
||||
|
||||
DoubleSelect dblSelect = new DoubleSelect(stack, req, res);
|
||||
container.inject(dblSelect);
|
||||
|
||||
dblSelect.evaluateParams();
|
||||
|
||||
assertEquals(nonceVal, dblSelect.getAttributes().get("nonce"));
|
||||
@@ -392,11 +404,35 @@ public class UIBeanTest extends StrutsInternalTestCase {
|
||||
session.invalidate();
|
||||
|
||||
DoubleSelect dblSelect = new DoubleSelect(stack, req, res);
|
||||
container.inject(dblSelect);
|
||||
|
||||
dblSelect.evaluateParams();
|
||||
|
||||
assertNull(dblSelect.getAttributes().get("nonce"));
|
||||
}
|
||||
|
||||
public void testNonceOfRequestAttribute() {
|
||||
Map<String, String> params = new HashMap<String, String>(){{
|
||||
put(StrutsConstants.STRUTS_CSP_NONCE_SOURCE, "request");
|
||||
}};
|
||||
initDispatcher(params);
|
||||
|
||||
String nonceVal = "r4nd0m";
|
||||
ValueStack stack = ActionContext.getContext().getValueStack();
|
||||
MockHttpServletRequest req = new MockHttpServletRequest();
|
||||
req.setAttribute("nonce", nonceVal);
|
||||
MockHttpServletResponse res = new MockHttpServletResponse();
|
||||
ActionContext actionContext = stack.getActionContext();
|
||||
actionContext.withServletRequest(req);
|
||||
|
||||
DoubleSelect dblSelect = new DoubleSelect(stack, req, res);
|
||||
container.inject(dblSelect);
|
||||
|
||||
dblSelect.evaluateParams();
|
||||
|
||||
assertEquals(nonceVal, dblSelect.getAttributes().get("nonce"));
|
||||
}
|
||||
|
||||
public void testSetNullUiStaticContentPath() {
|
||||
// given
|
||||
ValueStack stack = ActionContext.getContext().getValueStack();
|
||||
|
||||
@@ -312,7 +312,7 @@ public class CspInterceptorTest extends StrutsInternalTestCase {
|
||||
public static class CustomDefaultCspSettings extends DefaultCspSettings {
|
||||
|
||||
@Override
|
||||
protected String createPolicyFormat(HttpServletRequest request) {
|
||||
protected String createPolicyFormat(String nonceValue) {
|
||||
return "foo";
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -23,6 +23,8 @@ package org.apache.struts2.views.java.simple;
|
||||
import org.apache.struts2.components.ActionError;
|
||||
import org.apache.struts2.components.Anchor;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -72,6 +74,7 @@ public class ActionErrorTest extends AbstractTest {
|
||||
//errors are needed to setup stack
|
||||
super.setUp();
|
||||
this.tag = new ActionError(stack, request, response);
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
@@ -23,6 +23,8 @@ package org.apache.struts2.views.java.simple;
|
||||
|
||||
import org.apache.struts2.components.ActionError;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -72,6 +74,7 @@ public class ActionMessageTest extends AbstractTest {
|
||||
//errors are needed to setup stack
|
||||
super.setUp();
|
||||
this.tag = new ActionError(stack, request, response);
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
@@ -24,6 +24,8 @@ import org.apache.struts2.security.DefaultNotExcludedAcceptedPatternsChecker;
|
||||
import org.apache.struts2.components.Anchor;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.components.ServletUrlRenderer;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
public class AnchorTest extends AbstractTest {
|
||||
private Anchor tag;
|
||||
@@ -111,6 +113,7 @@ public class AnchorTest extends AbstractTest {
|
||||
this.tag = new Anchor(stack, request, response);
|
||||
this.tag.setUrlRenderer(new ServletUrlRenderer());
|
||||
this.tag.setNotExcludedAcceptedPatterns(new DefaultNotExcludedAcceptedPatternsChecker());
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
@@ -23,6 +23,8 @@ package org.apache.struts2.views.java.simple;
|
||||
import org.apache.struts2.security.DefaultNotExcludedAcceptedPatternsChecker;
|
||||
import org.apache.struts2.components.Checkbox;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
public class CheckboxTest extends AbstractCommonAttributesTest {
|
||||
private Checkbox tag;
|
||||
@@ -88,6 +90,7 @@ public class CheckboxTest extends AbstractCommonAttributesTest {
|
||||
super.setUp();
|
||||
tag = new Checkbox(stack, request, response);
|
||||
tag.setNotExcludedAcceptedPatterns(new DefaultNotExcludedAcceptedPatternsChecker());
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
@@ -22,6 +22,8 @@ package org.apache.struts2.views.java.simple;
|
||||
|
||||
import org.apache.struts2.components.DateTextField;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
public class DateTextFieldTest extends AbstractCommonAttributesTest {
|
||||
|
||||
@@ -56,6 +58,7 @@ public class DateTextFieldTest extends AbstractCommonAttributesTest {
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
this.tag = new DateTextField(stack, request, response);
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
@@ -22,6 +22,8 @@ package org.apache.struts2.views.java.simple;
|
||||
|
||||
import org.apache.struts2.components.FieldError;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -100,6 +102,7 @@ public class FieldErrorTest extends AbstractTest {
|
||||
//errors are needed to setup stack
|
||||
super.setUp();
|
||||
this.tag = new FieldError(stack, request, response);
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,6 +22,8 @@ package org.apache.struts2.views.java.simple;
|
||||
|
||||
import org.apache.struts2.components.File;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
public class FileTest extends AbstractCommonAttributesTest {
|
||||
private File tag;
|
||||
@@ -50,6 +52,7 @@ public class FileTest extends AbstractCommonAttributesTest {
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
this.tag = new File(stack, request, response);
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,6 +23,8 @@ package org.apache.struts2.views.java.simple;
|
||||
import org.apache.struts2.components.Form;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.components.UrlRenderer;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
import org.easymock.EasyMock;
|
||||
|
||||
public class FormTest extends AbstractCommonAttributesTest {
|
||||
@@ -80,5 +82,6 @@ public class FormTest extends AbstractCommonAttributesTest {
|
||||
UrlRenderer renderer = EasyMock.createNiceMock(UrlRenderer.class);
|
||||
EasyMock.replay(renderer);
|
||||
tag.setUrlRenderer(renderer);
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ package org.apache.struts2.views.java.simple;
|
||||
|
||||
import org.apache.struts2.components.Head;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
public class HeadTest extends AbstractTest {
|
||||
private Head tag;
|
||||
@@ -39,6 +41,7 @@ public class HeadTest extends AbstractTest {
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
this.tag = new Head(stack, request, response);
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
@@ -22,6 +22,8 @@ package org.apache.struts2.views.java.simple;
|
||||
|
||||
import org.apache.struts2.components.Hidden;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
public class HiddenTest extends AbstractTest {
|
||||
private Hidden tag;
|
||||
@@ -49,6 +51,7 @@ public class HiddenTest extends AbstractTest {
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
this.tag = new Hidden(stack, request, response);
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
@@ -22,6 +22,8 @@ package org.apache.struts2.views.java.simple;
|
||||
|
||||
import org.apache.struts2.components.Label;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
public class LabelTest extends AbstractCommonAttributesTest {
|
||||
private Label tag;
|
||||
@@ -48,6 +50,7 @@ public class LabelTest extends AbstractCommonAttributesTest {
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
this.tag = new Label(stack, request, response);
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,6 +20,8 @@ package org.apache.struts2.views.java.simple;
|
||||
|
||||
import org.apache.struts2.components.Link;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
public class LinkTest extends AbstractTest {
|
||||
|
||||
@@ -103,5 +105,6 @@ public class LinkTest extends AbstractTest {
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
this.tag = new Link(stack, request, response);
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
}
|
||||
|
||||
+5
-9
@@ -22,15 +22,14 @@ package org.apache.struts2.views.java.simple;
|
||||
|
||||
import org.apache.struts2.components.Password;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
public class PasswordTest extends AbstractCommonAttributesTest {
|
||||
|
||||
private Password tag;
|
||||
|
||||
public void testRenderPassword() throws Exception {
|
||||
super.setUp();
|
||||
this.tag = new Password(stack, request, response);
|
||||
|
||||
tag.setName("name");
|
||||
tag.setValue("val1");
|
||||
tag.setSize("10");
|
||||
@@ -51,9 +50,6 @@ public class PasswordTest extends AbstractCommonAttributesTest {
|
||||
}
|
||||
|
||||
public void testRenderPasswordShowIt() throws Exception {
|
||||
super.setUp();
|
||||
this.tag = new Password(stack, request, response);
|
||||
|
||||
tag.setName("name");
|
||||
tag.setValue("val1");
|
||||
tag.setSize("10");
|
||||
@@ -75,7 +71,9 @@ public class PasswordTest extends AbstractCommonAttributesTest {
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
//dont call base setup
|
||||
super.setUp();
|
||||
this.tag = new Password(stack, request, response);
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -85,8 +83,6 @@ public class PasswordTest extends AbstractCommonAttributesTest {
|
||||
|
||||
@Override
|
||||
protected UIBean getUIBean() throws Exception {
|
||||
super.setUp();
|
||||
this.tag = new Password(stack, request, response);
|
||||
return tag;
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -22,6 +22,8 @@ package org.apache.struts2.views.java.simple;
|
||||
|
||||
import org.apache.struts2.components.Reset;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
public class ResetTest extends AbstractCommonAttributesTest {
|
||||
private Reset tag;
|
||||
@@ -69,6 +71,7 @@ public class ResetTest extends AbstractCommonAttributesTest {
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
this.tag = new Reset(stack, request, response);
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
@@ -21,6 +21,8 @@ package org.apache.struts2.views.java.simple;
|
||||
import org.apache.struts2.security.DefaultNotExcludedAcceptedPatternsChecker;
|
||||
import org.apache.struts2.components.Script;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
|
||||
public class ScriptTest extends AbstractTest {
|
||||
@@ -72,5 +74,6 @@ public class ScriptTest extends AbstractTest {
|
||||
|
||||
this.tag = new Script(stack, request, response);
|
||||
tag.setNotExcludedAcceptedPatterns(new DefaultNotExcludedAcceptedPatternsChecker());
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -22,6 +22,8 @@ package org.apache.struts2.views.java.simple;
|
||||
|
||||
import org.apache.struts2.components.Select;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@@ -114,6 +116,7 @@ public class SelectTest extends AbstractCommonAttributesTest {
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
this.tag = new Select(stack, request, response);
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
@@ -22,6 +22,8 @@ package org.apache.struts2.views.java.simple;
|
||||
|
||||
import org.apache.struts2.components.Submit;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
public class SubmitTest extends AbstractCommonAttributesTest {
|
||||
private Submit tag;
|
||||
@@ -154,6 +156,7 @@ public class SubmitTest extends AbstractCommonAttributesTest {
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
this.tag = new Submit(stack, request, response);
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
@@ -22,6 +22,8 @@ package org.apache.struts2.views.java.simple;
|
||||
|
||||
import org.apache.struts2.components.TextArea;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
public class TextAreaTest extends AbstractCommonAttributesTest {
|
||||
private TextArea tag;
|
||||
@@ -71,6 +73,7 @@ public class TextAreaTest extends AbstractCommonAttributesTest {
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
this.tag = new TextArea(stack, request, response);
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
@@ -22,6 +22,8 @@ package org.apache.struts2.views.java.simple;
|
||||
|
||||
import org.apache.struts2.components.TextField;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
public class TextFieldTest extends AbstractCommonAttributesTest {
|
||||
private TextField tag;
|
||||
@@ -52,6 +54,7 @@ public class TextFieldTest extends AbstractCommonAttributesTest {
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
this.tag = new TextField(stack, request, response);
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
@@ -23,6 +23,8 @@ package org.apache.struts2.views.java.simple;
|
||||
import org.apache.struts2.ActionContext;
|
||||
import org.apache.struts2.components.Token;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.interceptor.csp.CspNonceSource;
|
||||
import org.apache.struts2.interceptor.csp.StrutsCspNonceReader;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -49,6 +51,7 @@ public class TokenTest extends AbstractTest {
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
this.tag = new Token(stack, request, response);
|
||||
this.tag.setCspNonceReader(new StrutsCspNonceReader(CspNonceSource.SESSION.name()));
|
||||
|
||||
ActionContext.of()
|
||||
.withSession(new HashMap<>())
|
||||
|
||||
Reference in New Issue
Block a user