Class StrutsParameterAuthorizer

java.lang.Object
org.apache.struts2.interceptor.parameter.StrutsParameterAuthorizer
All Implemented Interfaces:
ParameterAuthorizer

public class StrutsParameterAuthorizer extends Object implements ParameterAuthorizer
Default implementation of ParameterAuthorizer that checks StrutsParameter annotations on the target object's members to determine whether a parameter is authorized for injection.

This implementation extracts the authorization logic from ParametersInterceptor so that it can be shared with other input channels (JSON plugin, REST plugin) without duplicating code.

Unlike ParametersInterceptor, this implementation does NOT perform OGNL ThreadAllowlist side effects. Those remain specific to the OGNL-based parameter injection path.

Since:
7.2.0
  • Constructor Details

    • StrutsParameterAuthorizer

      public StrutsParameterAuthorizer()
  • Method Details

    • setOgnlUtil

      public void setOgnlUtil(OgnlUtil ognlUtil)
    • setProxyService

      public void setProxyService(ProxyService proxyService)
    • setDevMode

      public void setDevMode(String mode)
    • setRequireAnnotations

      public void setRequireAnnotations(String requireAnnotations)
    • setRequireAnnotationsTransitionMode

      public void setRequireAnnotationsTransitionMode(String transitionMode)
    • resolveTarget

      public Object resolveTarget(Object action)
      Description copied from interface: ParameterAuthorizer
      Resolves the target object whose annotations should be checked for authorization. For ModelDriven actions, the default implementation returns the action itself; the production implementation (StrutsParameterAuthorizer) overrides this to return the model from the value stack.

      Callers that need both authorization checks AND the resolved target (e.g. for downstream OGNL allowlisting) should call this once and reuse the result.

      This is a default method to preserve the interface as a functional interface (SAM) for lambda-based test stubs.

      Specified by:
      resolveTarget in interface ParameterAuthorizer
      Parameters:
      action - the action instance
      Returns:
      the resolved target — either the action or its model
    • isAuthorized

      public boolean isAuthorized(String parameterName, Object target, Object action)
      Description copied from interface: ParameterAuthorizer
      Determines whether a parameter with the given name is authorized for injection into the given target object.

      When struts.parameters.requireAnnotations is false, this method always returns true for backward compatibility.

      Specified by:
      isAuthorized in interface ParameterAuthorizer
      Parameters:
      parameterName - the parameter name (e.g. "name", "address.city", "items[0].name")
      target - the object receiving the parameter value (the action, or the model for ModelDriven actions)
      action - the action instance; used to detect ModelDriven exemption (when target != action, the target is the model and is exempt from annotation requirements)
      Returns:
      true if the parameter is authorized for injection, false otherwise
    • isAuthorizedOnModelDrivenAction

      protected boolean isAuthorizedOnModelDrivenAction(String rootProperty, Object model, Object action, long paramDepth)
      Decides authorization for a ModelDriven action, whose model is on top of the value stack.

      Returning an object from getModel() declares that object to be request surface, so anything the model itself can take is exempt from the StrutsParameter requirement. The exemption stops there: OGNL resolves the parameter name against the whole stack, which also holds the action, so a property declared on the action is still subject to the annotation requirement. Without that distinction a ModelDriven action would silently expose its own members.

      A property declared on neither is allowed: typically it is bound by a custom OGNL property accessor on the model, such as a Map-backed model. That fallback guarantees less than it may appear to - only that the name reaches no member declaresProperty(java.lang.Object, java.lang.String, long) can see. OGNL walks the whole stack, so such a name can still land on the action wherever the action absorbs it by a route introspection here does not model, being a Map itself for instance. That is no more permissive than the blanket exemption this scoping replaces.

      class is the exception to that fallback: it is invisible to introspection here rather than absent, so it is rejected instead of taking the fallback, which keeps a ModelDriven action from handing OGNL a class path that the ordinary non-ModelDriven path would have rejected for want of an annotation.

    • declaresProperty

      protected boolean declaresProperty(Object target, String property, long paramDepth)
      Whether target can itself take property at this depth - as a bean property whose relevant accessor exists, the setter for a depth-0 parameter and the getter for a nested one, or as a public instance field. Any StrutsParameter annotation is irrelevant here; this asks only what the object can absorb.

      It has to be bindability rather than the name alone, because OGNL walks the stack until an object actually accepts the assignment. A model which merely names the property without being able to take it - a getter-only property under a depth-0 parameter, say - does not absorb that parameter: OGNL moves on to the action, and an exemption granted on the name alone would hand over the action's own member, which is the very thing this scoping exists to prevent. Inherited public fields count for the same reason, that OGNL can set them.

    • findBindableAccessor

      protected Optional<Method> findBindableAccessor(Object target, String property, long paramDepth)
      The method OGNL would go through to bind property on target at this depth: the setter for a depth-0 parameter, the getter for a nested one.

      The setter is matched the way OGNL matches it - a public instance method named set plus the capitalised property name, taking one argument - and not through PropertyDescriptor.getWriteMethod(), which Introspector only fills in for a void setter. A fluent setter returning this is just as bindable to OGNL, so it has to be just as visible here, both to carry a StrutsParameter annotation and to count as declared on a ModelDriven action.

      Where several setters qualify, the one declared furthest down the hierarchy wins - an override is what OGNL invokes and what the developer annotated, while the erased setter of a generic superclass is listed alongside it and carries no annotation - and among overloads declared at that level an annotated one, since annotating any overload declares the property request surface.

    • declaresBindablePublicField

      protected boolean declaresBindablePublicField(Object target, String property, long paramDepth)
      Whether target exposes property as a public instance field that this parameter could bind through. Class.getFields() covers inherited fields as well as declared ones, an inherited public field being just as settable as a declared one. Static fields are not per-instance request surface, and a final field cannot take a depth-0 assignment, so neither counts as absorbing the parameter.

      Scanning the fields and matching the name here, rather than looking the name up with getField, keeps the request-derived property name out of a reflection lookup. The two select the same fields.

    • hasValidAnnotatedMember

      protected boolean hasValidAnnotatedMember(String rootProperty, Object target, long paramDepth)
    • hasValidAnnotatedPropertyDescriptor

      @Deprecated(since="7.4.0", forRemoval=true) protected boolean hasValidAnnotatedPropertyDescriptor(Object target, PropertyDescriptor propDesc, long paramDepth)
      Deprecated, for removal: This API element is subject to removal in a future version.
    • hasValidAnnotatedMethod

      protected boolean hasValidAnnotatedMethod(Object target, Method method, long paramDepth)
    • hasValidAnnotatedField

      protected boolean hasValidAnnotatedField(Object target, String fieldName, long paramDepth)
    • getPermittedInjectionDepth

      protected int getPermittedInjectionDepth(AnnotatedElement element)
    • getParameterAnnotation

      protected StrutsParameter getParameterAnnotation(AnnotatedElement element)
    • ultimateClass

      protected Class<?> ultimateClass(Object target)
    • getBeanInfo

      protected BeanInfo getBeanInfo(Object target)