WW-5184 - Added ParameterValueAware interface and unit test

This commit is contained in:
Brian Andle
2022-06-07 21:50:34 -07:00
parent 5763476830
commit 584634a9b5
3 changed files with 88 additions and 7 deletions
@@ -0,0 +1,37 @@
/*
* 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 com.opensymphony.xwork2.interceptor;
/**
* This interface is implemented by actions that want to declare acceptable parameter value. Works in conjunction with {@link
* ParametersInterceptor}. For example, actions may want to create a white list of parameter values they will accept or a
* blacklist of parameter values they will reject to prevent clients from setting other unexpected (and possibly dangerous)
* parameter values.
*/
public interface ParameterValueAware {
/**
* Tests if the the action will accept the parameter with the given value.
*
* @param parameterValue the parameter value
* @return <tt>true</tt> if accepted, <tt>false</tt> otherwise
*/
boolean acceptableParameterValue(String parameterValue);
}
@@ -191,7 +191,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
for (Map.Entry<String, Parameter> entry : params.entrySet()) {
String parameterName = entry.getKey();
boolean isAcceptableParameter = isAcceptableParameter(parameterName, action);
isAcceptableParameter &= isAcceptableParameterValue(entry.getValue());
isAcceptableParameter &= isAcceptableParameterValue(entry.getValue(), action);
if (isAcceptableParameter) {
acceptableParameters.put(parameterName, entry.getValue());
@@ -280,14 +280,14 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
* @param action current action
* @return true if parameter is accepted
*/
protected boolean isAcceptableParameterValue(Parameter param) {
protected boolean isAcceptableParameterValue(Parameter param, Object action) {
ParameterValueAware parameterValueAware = (action instanceof ParameterValueAware) ? (ParameterValueAware) action : null;
boolean acceptableParmValue = (parameterValueAware == null || parameterValueAware.acceptableParameterValue(param.getValue()));
if(hasParamValuesToExclude() || hasParamValuesToAccept()) {
// We have something to check.
return acceptableValue(param.getName(), param.getValue());
} else {
// No exclude/accept defined. Return true/allowed.
return true;
// Additional validations to process
acceptableParmValue &= acceptableValue(param.getName(), param.getValue());
}
return acceptableParmValue;
}
/**
@@ -888,6 +888,50 @@ public class ParametersInterceptorTest extends XWorkTestCase {
pi.setParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build());
assertEquals(expected, actual);
}
public void testExcludedParametersValuesAreIgnoredWithParameterValueAware() throws Exception {
ParametersInterceptor pi = createParametersInterceptor();
// Contains (based on pattern)
pi.setExcludeValuePatterns(".*\\$\\{.*?\\}.*,.*%\\{.*?\\}.*");
assertTrue("${2*2} was excluded by isParamValueExcluded", pi.isParamValueExcluded("${2*2}"));
final Map<String, Object> actual = injectValueStackFactory(pi);
ValueStack stack = injectValueStack(actual);
final Map<String, Object> expected = new HashMap<String, Object>() {
{
// acceptableParameterValue only allows fooValue even though fooKey2 and fooKey3 pass the excludeValuePatterns check
put("fooKey", "fooValue");
}
};
Object a = new ParameterValueAware() {
@Override
public boolean acceptableParameterValue(String parameterValue) {
// Only fooValue will be allowed because the excludeValuePatterns will block ${2+2}
return parameterValue.equals("fooValue") || parameterValue.equals("${2+2}");
}
};
Map<String, Object> parameters = new HashMap<String, Object>() {
{
put("barKey$", "${2+2}");
put("barKey2$", "foo${2+2}");
put("barKey3$", "foo${2+2}foo");
put("barKey%", "%{2+2}");
put("barKey2%", "foo%{2+2}");
put("barKey3%", "foo%{2+2}foo");
put("allowedKey", "${foo}");
put("allowedKey2", "%{bar}");
put("fooKey", "fooValue");
put("fooKey2", "fooValue2");
put("fooKey3", "");
}
};
pi.setParameters(a, stack, HttpParameters.create(parameters).build());
assertEquals(expected, actual);
}
private ValueStack injectValueStack(Map<String, Object> actual) {