[
https://issues.apache.org/jira/browse/WW-5771?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18126704#comment-18126704
]
Lukasz Lenart edited comment on WW-5771 at 10/13/26 11:47 AM:
--------------------------------------------------------------
Thanks for the detailed report and the reproducer. You're right about the
cause: in 7.4.0, {{findBindableAccessor}} only builds {{set}} plus the
capitalised name, so an annotated {{seteMail}} isn't found.
This was already fixed by WW-5759 in PR
[#1992|https://github.com/apache/struts/pull/1992], which will ship in 7.5.0.
The authorizer now tries the same accessor names OGNL does, in the same order:
{{seteMail}} first, then {{setEMail}}. In the same change, Struts moves to OGNL
3.4.14 or later ({{main}} is on 3.4.15).
One note on the version matrix: 7.4.0 ships OGNL 3.4.12 and 7.3.0 ships 3.4.11.
Neither of those bundled versions resolves {{seteMail}}, so with them the
parameter wasn't bound on 7.3.0 either. The difference you saw between 7.3.0
and 7.4.0 shows up when the application overrides OGNL to 3.4.14 or later.
Until 7.5.0, the workaround you found (annotating a {{setEMail}} alias) is the
way to go on 7.4.0.
Closing as a duplicate of WW-5759.
was (Author: lukaszlenart):
Thanks for the detailed report and the reproducer. You're right about the
cause: in 7.4.0, {{findBindableAccessor}} only builds {{set}} + the capitalised
name, so an annotated {{seteMail}} isn't found.
This was already fixed by WW-5759 in PR
[#1992|https://github.com/apache/struts/pull/1992], which will ship in 7.5.0.
The authorizer now tries the same accessor names OGNL does, in the same order:
{{seteMail}} first, then {{setEMail}}. In the same change, Struts moves to OGNL
3.4.14+ ({{main}} is on 3.4.15).
One note on the version matrix: 7.4.0 ships OGNL 3.4.12 and 7.3.0 ships 3.4.11.
Neither of those bundled versions resolves {{seteMail}}, so with them the
parameter wasn't bound on 7.3.0 either. The difference you saw between 7.3.0
and 7.4.0 shows up when the application overrides OGNL to 3.4.14 or later.
Until 7.5.0, the workaround you found (annotating a {{setEMail}} alias) is the
way to go on 7.4.0.
Closing as a duplicate of WW-5759.
> StrutsParameterAuthorizer only matches naively capitalized setters, rejecting
> annotated JavaBeans-compliant setters like seteMail
> ---------------------------------------------------------------------------------------------------------------------------------
>
> Key: WW-5771
> URL: https://issues.apache.org/jira/browse/WW-5771
> Project: Struts 2
> Issue Type: Bug
> Components: Core Interceptors
> Affects Versions: 7.4.0
> Reporter: Niklas Neesen
> Priority: Major
> Fix For: 7.5.0
>
>
> Since 7.4.0, {{StrutsParameterAuthorizer.findBindableAccessor}} resolves the
> setter for a depth-0 parameter by building the name itself:
> {code:java}
> String setterName = "set" + Character.toUpperCase(property.charAt(0)) +
> property.substring(1);
> {code}
> For a property whose name starts with a lowercase letter followed by an
> uppercase letter (e.g. {{eMail}}), this only finds the naively capitalized
> {{setEMail}}. Per the JavaBeans specification (the inverse of
> {{Introspector.decapitalize}}), the accessor for property {{eMail}} is
> {{seteMail}} — which is what 7.3.0 found via
> {{PropertyDescriptor#getWriteMethod}} and what developers annotated with
> {{@StrutsParameter}}.
> The result: an action with a correctly annotated, spec-compliant setter
> {code:java}
> private String eMail;
> @StrutsParameter
> public void seteMail(String eMail) { this.eMail = eMail; }
> {code}
> passes authorization on 7.3.0 but is rejected on 7.4.0 — the parameter is
> silently dropped (in production mode nothing is logged above debug level),
> the field stays null, and the regression surfaces only as downstream
> application errors.
> The Javadoc on {{findBindableAccessor}} says the setter is "matched the way
> OGNL matches it". That was true for OGNL 3.4.0-3.4.13, which had exactly this
> naive-capitalization bug — but it was fixed in OGNL 3.4.14
> ([https://github.com/orphan-oss/ognl/issues/643],
> [https://github.com/orphan-oss/ognl/pull/644]): OGNL now resolves both base
> names, spec-compliant first. So on current Struts 7.4.0 + OGNL 3.4.14+, the
> authorizer and the binder it guards disagree in both directions:
> * The authorizer inspects {{setEMail}} (and requires the annotation there),
> while OGNL binds through {{seteMail}}.
> * An annotation on the spec-compliant setter — the method OGNL actually
> invokes — is invisible to the authorizer.
> h3. Standalone reproducer
> Only struts2-core and ognl on the classpath:
> {code:java}
> public class Repro {
> public static class SpecCompliantAction {
> private String eMail;
> @StrutsParameter
> public void seteMail(String v) { this.eMail = v; }
> }
> public static void main(String[] args) {
> StrutsParameterAuthorizer auth = new StrutsParameterAuthorizer();
> auth.setRequireAnnotations("true");
> auth.setOgnlUtil(/* OgnlUtil with default caches */);
> auth.setProxyService(/* no-op ProxyService */);
> SpecCompliantAction a = new SpecCompliantAction();
> // 7.3.0: true — 7.4.0: false
> System.out.println(auth.isAuthorized("eMail", a, a));
> }
> }
> {code}
> Observed matrix:
> || ||annotated {{seteMail}} only||annotated {{seteMail}} + annotated alias
> {{setEMail}}||
> ||7.3.0|authorized|authorized|
> ||7.4.0|*rejected*|authorized|
> h3. Suggested fix
> Derive the candidate base names the same way OGNL >= 3.4.14 does
> ({{OgnlRuntime.accessorBaseNames}}): for a lowercase-then-uppercase property
> name, look up both {{set<property>}} and {{set<Capitalized property>}},
> spec-compliant name first, and accept an annotation on whichever method
> qualifies. The same applies to the getter lookup for nested parameters if it
> ever moves away from {{PropertyDescriptor}}s.
> Found while upgrading 7.3.0 → 7.4.0: parameters bound to properties of this
> naming pattern were silently dropped despite annotated, spec-compliant
> setters, and only annotating a naively capitalized alias setter restores them.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)