This is an automated email from the ASF dual-hosted git repository. lukaszlenart pushed a commit to branch WW-4858-json-parameter-filtering in repository https://gitbox.apache.org/repos/asf/struts.git
commit 064e59a99438e74d1bb21bf6d7dbee9926ddf345 Author: Lukasz Lenart <[email protected]> AuthorDate: Wed Jul 8 20:39:47 2026 +0200 WW-4858 feat(json): honor ParameterNameAware and ParameterValueAware on JSON population Co-Authored-By: Claude Opus 4.8 <[email protected]> --- .../org/apache/struts2/json/JSONInterceptor.java | 23 +++++++- .../apache/struts2/json/JSONInterceptorTest.java | 32 +++++++++++ .../struts2/json/ParameterAwareTestAction.java | 63 ++++++++++++++++++++++ 3 files changed, 117 insertions(+), 1 deletion(-) diff --git a/plugins/json/src/main/java/org/apache/struts2/json/JSONInterceptor.java b/plugins/json/src/main/java/org/apache/struts2/json/JSONInterceptor.java index c508fee86..37fb2fec5 100644 --- a/plugins/json/src/main/java/org/apache/struts2/json/JSONInterceptor.java +++ b/plugins/json/src/main/java/org/apache/struts2/json/JSONInterceptor.java @@ -19,6 +19,8 @@ package org.apache.struts2.json; import org.apache.struts2.action.Action; +import org.apache.struts2.action.ParameterNameAware; +import org.apache.struts2.action.ParameterValueAware; import org.apache.struts2.ActionInvocation; import org.apache.struts2.inject.Inject; import org.apache.struts2.interceptor.AbstractInterceptor; @@ -239,6 +241,8 @@ public class JSONInterceptor extends AbstractInterceptor { filterUnacceptableKeysRecursive((Map) value, fullPath, target, action); } else if (value instanceof java.util.List) { filterUnacceptableList((java.util.List) value, fullPath, target, action); + } else if (!isAcceptableValue(fullPath, value, action)) { + it.remove(); } } } @@ -248,11 +252,15 @@ public class JSONInterceptor extends AbstractInterceptor { // Use prefix+"[0]" so list element properties pick up one extra '[' in their path, // matching the indexed-path semantics of ParametersInterceptor (e.g. "items[0].key"). String elementPrefix = prefix + "[0]"; - for (Object item : list) { + Iterator it = list.iterator(); + while (it.hasNext()) { + Object item = it.next(); if (item instanceof Map) { filterUnacceptableKeysRecursive((Map) item, elementPrefix, target, action); } else if (item instanceof java.util.List) { filterUnacceptableList((java.util.List) item, elementPrefix, target, action); + } else if (!isAcceptableValue(elementPrefix, item, action)) { + it.remove(); } } } @@ -276,6 +284,19 @@ public class JSONInterceptor extends AbstractInterceptor { fullPath, target.getClass().getName()); return false; } + if (action instanceof ParameterNameAware nameAware && !nameAware.acceptableParameterName(fullPath)) { + LOG.debug("JSON body parameter [{}] rejected by ParameterNameAware action", fullPath); + return false; + } + return true; + } + + private boolean isAcceptableValue(String fullPath, Object value, Object action) { + String stringValue = value == null ? null : String.valueOf(value); + if (action instanceof ParameterValueAware valueAware && !valueAware.acceptableParameterValue(stringValue)) { + LOG.debug("JSON body value for parameter [{}] rejected by ParameterValueAware action", fullPath); + return false; + } return true; } diff --git a/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java b/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java index 82a562f00..6287ae892 100644 --- a/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java +++ b/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java @@ -765,6 +765,38 @@ public class JSONInterceptorTest extends StrutsTestCase { assertNull(action.getFoo()); } + public void testParameterNameAwareRejectsKey() throws Exception { + this.request.setContent("{\"foo\":\"a\", \"bar\":\"b\"}".getBytes()); + this.request.addHeader("Content-Type", "application/json"); + + JSONInterceptor interceptor = createInterceptor(); + ParameterAwareTestAction action = new ParameterAwareTestAction(); + + this.invocation.setAction(action); + this.invocation.getStack().push(action); + + interceptor.intercept(this.invocation); + + assertEquals("a", action.getFoo()); + assertNull(action.getBar()); + } + + public void testParameterValueAwareRejectsValue() throws Exception { + this.request.setContent("{\"foo\":\"blocked\", \"baz\":\"good\"}".getBytes()); + this.request.addHeader("Content-Type", "application/json"); + + JSONInterceptor interceptor = createInterceptor(); + ParameterAwareTestAction action = new ParameterAwareTestAction(); + + this.invocation.setAction(action); + this.invocation.getStack().push(action); + + interceptor.intercept(this.invocation); + + assertNull(action.getFoo()); + assertEquals("good", action.getBaz()); + } + @Override protected void setUp() throws Exception { super.setUp(); diff --git a/plugins/json/src/test/java/org/apache/struts2/json/ParameterAwareTestAction.java b/plugins/json/src/test/java/org/apache/struts2/json/ParameterAwareTestAction.java new file mode 100644 index 000000000..d71287cd9 --- /dev/null +++ b/plugins/json/src/test/java/org/apache/struts2/json/ParameterAwareTestAction.java @@ -0,0 +1,63 @@ +/* + * 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.json; + +import org.apache.struts2.action.ParameterNameAware; +import org.apache.struts2.action.ParameterValueAware; + +public class ParameterAwareTestAction implements ParameterNameAware, ParameterValueAware { + + private String foo; + private String bar; + private String baz; + + public String getFoo() { + return foo; + } + + public void setFoo(String foo) { + this.foo = foo; + } + + public String getBar() { + return bar; + } + + public void setBar(String bar) { + this.bar = bar; + } + + public String getBaz() { + return baz; + } + + public void setBaz(String baz) { + this.baz = baz; + } + + @Override + public boolean acceptableParameterName(String parameterName) { + return !"bar".equals(parameterName); + } + + @Override + public boolean acceptableParameterValue(String parameterValue) { + return !"blocked".equals(parameterValue); + } +}
