mirror of
https://github.com/apache/struts.git
synced 2026-08-11 01:27:14 +00:00
09d03286f8
* WW-5626 spike: validate Jackson per-property authorization mechanism Validates that the Approach C design is feasible before committing to a detailed implementation plan. Wraps each SettableBeanProperty via BeanDeserializerModifier; intercepts deserializeAndSet to authorize against a path built from a ThreadLocal Deque; uses skipChildren() to discard unauthorized values; uses [0] suffix for collection/map/array elements to match ParametersInterceptor depth semantics. Findings: - Delegating base class via 'protected delegate' field is the right pattern - addOrReplaceProperty(prop, true) is the correct builder API - Reject-at-parent skips all nested deserialization (better security than two-phase copy: setter side effects on unauthorized properties never fire) - JavaType#isCollectionLikeType/isMapLikeType/isArrayType detects the indexed-path case Spike is kept under .../spike/ as a learning artifact; it will be replaced by production code + tests in subsequent commits. * WW-5626 add ParameterAuthorizationContext for deserializer-level authorization Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * WW-5626 address review feedback on ParameterAuthorizationContext Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * WW-5626 add AuthorizationAwareContentTypeHandler marker interface * WW-5626 add AuthorizingSettableBeanProperty for Jackson per-property authorization * WW-5626 add ParameterAuthorizingModule installing the property wrapper on Jackson mappers * WW-5626 register ParameterAuthorizingModule on default Jackson REST handlers * WW-5626 use AuthorizationAwareContentTypeHandler path when handler supports it * WW-5626 add integration tests proving the new Jackson authorization path is used * WW-5626 deprecate XStreamHandler in favor of JacksonXmlHandler * WW-5626 remove Jackson auth spike; replaced by production tests * WW-5626 make JuneauXmlHandler authorization-aware via post-parse walk Implements AuthorizationAwareContentTypeHandler. When ParameterAuthorizationContext is active (set by ContentTypeInterceptor when requireAnnotations=true), the handler walks the parsed result tree and copies only authorized properties to the target, descending into nested beans/collections/maps/arrays with indexed-path semantics ([0] suffix) for parity with ParametersInterceptor. Note: Juneau parses the entire result tree before our walk runs, so setter side effects on transient nested objects can fire even for unauthorized properties — those transient objects are then discarded. This is functionally equivalent to the legacy two-phase copy in ContentTypeInterceptor; only the Jackson handlers achieve the stronger guarantee where unauthorized subtrees are never instantiated at all (they use Jackson's BeanDeserializerModifier + skipChildren). When no context is bound (default config), behavior is unchanged: parser.parse + BeanUtils.copyProperties. * WW-5626 add JuneauXmlHandler integration tests for @StrutsParameter authorization * WW-5626 test(rest): cover JuneauXmlHandler post-parse walk for collections, maps, arrays Sonar reported 51 uncovered new lines in JuneauXmlHandler (48.8% coverage on the post-parse authorization walk — the security-critical code path the branch exists to introduce). Add integration coverage for the previously-uncovered branches: - collection-of-scalars (List<String> tags) - collection-of-beans (List<Address> addresses) - map-of-scalars (Map<String,String> attributes) - array-of-scalars (String[] aliases) - empty collection - malformed XML wrapped as IOException Also drop two unnecessary casts (Sonar S1905) on lines 243/252 — the unchecked conversion happens at the return statement, the explicit casts were redundant under the existing @SuppressWarnings("unchecked"). Add @Override on the inline AnyConstraintMatcher.matches override (Sonar S1161). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * WW-5626 test(rest): cover AuthorizingSettableBeanProperty builder-path deserialization Sonar reported 11 uncovered new lines on AuthorizingSettableBeanProperty (66.7% coverage). All 11 are in deserializeSetAndReturn — the alternate Jackson entry point used for builder-pattern deserialization, never triggered by setter-based fixtures like Person. Add an @JsonDeserialize(builder=...) fixture (ImmutablePerson) that forces Jackson to use BuilderBasedDeserializer, which dispatches property writes through deserializeSetAndReturn. Three new tests exercise the path: inactive-context pass-through, top-level authorization, and full rejection. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * WW-5626 refactor(rest): extract helpers from ContentTypeInterceptor.intercept Sonar S3776 flagged intercept() at cognitive complexity 16 (limit 15). Extract the body-handling branches into named helpers: - openBodyReader: encoding-aware reader from the request InputStream - applyRequestBody: dispatcher between requireAnnotations on/off paths - applyWithAuthorizationContext: bind + delegate + unbind for AuthorizationAware handlers - applyTwoPhaseDeserialize: legacy fresh-instance + copyAuthorizedProperties path intercept() drops to ~12 lines and reads as a flat sequence: resolve target, delegate body application, invoke. Each helper carries the comment that explains the security model for its branch. Add @Override on the inline AnyConstraintMatcher.matches override (Sonar S1161). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Struts 2 Core
This is a core of the Apache Struts framework and all other modules depend on it. It requires Java 8 at minimum and a Servlet container supporting Java Servlet API 3.1 at least.
Installation
Just drop this plugin into WEB-INF/lib folder or add it as Maven dependency