[ https://issues.apache.org/jira/browse/WW-5352?focusedWorklogId=903106&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-903106 ]
ASF GitHub Bot logged work on WW-5352: -------------------------------------- Author: ASF GitHub Bot Created on: 01/Feb/24 16:08 Start Date: 01/Feb/24 16:08 Worklog Time Spent: 10m Work Description: sepe81 commented on code in PR #227: URL: https://github.com/apache/struts-site/pull/227#discussion_r1474708287 ########## source/security/index.md: ########## @@ -113,8 +113,75 @@ header to each JSP file <%@ page contentType="text/html; charset=UTF-8" %> ``` +### Defining and annotating your Action parameters + +> Note: Since 6.4 using `struts.parameters.requireAnnotations=true`. Or by default from 7.0. + +Request parameters, such as those submitted by a form, can be stored on your Struts Action class by defining getters and +setters for them. For example, if you have a form with a field called `name`, you can store the value of that field by +defining a `public void setName(String name)` method on your Action class, and then importantly, annotating this method +with `@StrutsParameter`. The presence of this annotation indicates that the method is intended for parameter injection +and is safe to be invoked by any user who can view the Action. + +```java +private String name; + +@StrutsParameter +public void setName(String name) { + this.name = name; +} +``` + +If you wish to populate a DTO (Data Transfer Object) instead of setting the parameters directly on the Action class, you +can define a getter for the DTO on your Action class instead. For example, define a method `public MyDto getFormData()` +which is also annotated by `@StrutsParameter(depth = 1)`. Then, a parameter with name `formData.fullName` will be mapped +to the setter `setFullName` on that DTO. Note that the `@StrutsParameter` annotation has a `depth` field which dictates +the depth to which parameter injection is permitted. The default value is 0, which only allows setting parameters +directly on the Action class as in the first example. A `depth` of 1 indicates that the immediate public properties of +an object returned by the getter are permitted to be set. If you have further nested objects, you can increase +the `depth` accordingly. Do not set this `depth` field to a value greater than the minimum required for your use case. + +```java +private MyDto formData = new MyDto(); + +@StrutsParameter(depth = 1) +public MyDto getFormData() { + return formData; +} + +public static class MyDto { + private String fullName; + + public void setFullName(String fullName) { + this.fullName = fullName; + } +} +``` + +It is critical that any method you annotate with `@StrutsParameter` is safe for any user who can view that corresponding +action to invoke (including any public methods on objects returned by that method and so forth). Any getters you +annotate should only ever return a DTO or a collection/hierarchy of DTOs. Do NOT mix business logic or service +references with your parameter injection methods and DTOs. Additionally, any database DTOs should be entirely separate +from request parameter/form DTOs. + +Do NOT under any circumstance, annotate a method that returns one of the following unsafe objects: Review Comment: ```suggestion Do NOT, under any circumstance, annotate a method that returns one of the following unsafe objects: ``` ########## source/security/index.md: ########## @@ -113,8 +113,75 @@ header to each JSP file <%@ page contentType="text/html; charset=UTF-8" %> ``` +### Defining and annotating your Action parameters + +> Note: Since 6.4 using `struts.parameters.requireAnnotations=true`. Or by default from 7.0. + +Request parameters, such as those submitted by a form, can be stored on your Struts Action class by defining getters and +setters for them. For example, if you have a form with a field called `name`, you can store the value of that field by +defining a `public void setName(String name)` method on your Action class, and then importantly, annotating this method +with `@StrutsParameter`. The presence of this annotation indicates that the method is intended for parameter injection +and is safe to be invoked by any user who can view the Action. + +```java +private String name; + +@StrutsParameter +public void setName(String name) { + this.name = name; +} +``` + +If you wish to populate a DTO (Data Transfer Object) instead of setting the parameters directly on the Action class, you +can define a getter for the DTO on your Action class instead. For example, define a method `public MyDto getFormData()` +which is also annotated by `@StrutsParameter(depth = 1)`. Then, a parameter with name `formData.fullName` will be mapped +to the setter `setFullName` on that DTO. Note that the `@StrutsParameter` annotation has a `depth` field which dictates +the depth to which parameter injection is permitted. The default value is 0, which only allows setting parameters +directly on the Action class as in the first example. A `depth` of 1 indicates that the immediate public properties of +an object returned by the getter are permitted to be set. If you have further nested objects, you can increase +the `depth` accordingly. Do not set this `depth` field to a value greater than the minimum required for your use case. + +```java +private MyDto formData = new MyDto(); + +@StrutsParameter(depth = 1) +public MyDto getFormData() { + return formData; +} + +public static class MyDto { + private String fullName; + + public void setFullName(String fullName) { + this.fullName = fullName; + } +} +``` + +It is critical that any method you annotate with `@StrutsParameter` is safe for any user who can view that corresponding +action to invoke (including any public methods on objects returned by that method and so forth). Any getters you +annotate should only ever return a DTO or a collection/hierarchy of DTOs. Do NOT mix business logic or service +references with your parameter injection methods and DTOs. Additionally, any database DTOs should be entirely separate +from request parameter/form DTOs. + +Do NOT under any circumstance, annotate a method that returns one of the following unsafe objects: +- live Hibernate persistent objects +- container or Spring-managed beans, or any other live components/services +- objects (or objects that contain references to objects) that contain setter methods that are used for anything other + than setting form parameter values + +If you are finding updating your application with this new annotation time-consuming, you can temporarily combine the +above option with `struts.parameters.requireAnnotations.transitionMode=true`. When this mode is enabled, only 'nested' +parameters, i.e. DTOs or Collections represented by public getters on Action classes, will require annotations. This +means public setters will still be exposed for parameter injection. Notably, +the [auto-allowlisting capability](#allowlist-capability), which is also supported by these annotations, is not degraded +in any way, so it proves a useful transitioning option for applications that wish to enable the OGNL allowlist as soon +as possible. + ### Do not define setters when not needed +> Note: Only relevant if you are not using `struts.parameters.requireAnnotations=true` as per the previous section. + You should carefully design your actions without exposing anything via setters and getters, thus can leads to potential Review Comment: ```suggestion You should carefully design your actions without exposing anything via setters and getters, thus can lead to potential ``` Issue Time Tracking ------------------- Worklog Id: (was: 903106) Time Spent: 10h 40m (was: 10.5h) > Implement annotation mechanism for injectable fields via parameters > ------------------------------------------------------------------- > > Key: WW-5352 > URL: https://issues.apache.org/jira/browse/WW-5352 > Project: Struts 2 > Issue Type: Improvement > Components: Core, Core Interceptors > Reporter: Kusal Kithul-Godage > Priority: Minor > Fix For: 6.4.0 > > Time Spent: 10h 40m > Remaining Estimate: 0h > > struts.parameters.requireAnnotations > > Require an explicit annotation '@StrutsParameter' on one of: > Getter/Setter/Field/ReturnType for injecting parameters. > > This mechanism is intended to be a more usable replacement for > 'ParameterNameAware' -- This message was sent by Atlassian Jira (v8.20.10#820010)