You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
91 lines
3.1 KiB
91 lines
3.1 KiB
xref:core/validation/beans-beans.adoc#beans-binding[Data binding] for web requests involves |
|
binding request parameters to a model object. By default, request parameters can be bound |
|
to any public property of the model object, which means malicious clients can provide |
|
extra values for properties that exist in the model object graph, but are not expected to |
|
be set. This is why model object design requires careful consideration. |
|
|
|
TIP: The model object, and its nested object graph is also sometimes referred to as a |
|
_command object_, _form-backing object_, or _POJO_ (Plain Old Java Object). |
|
|
|
A good practice is to use a _dedicated model object_ rather than exposing your domain |
|
model such as JPA or Hibernate entities for web data binding. For example, on a form to |
|
change an email address, create a `ChangeEmailForm` model object that declares only |
|
the properties required for the input: |
|
|
|
[source,java,indent=0,subs="verbatim,quotes"] |
|
---- |
|
public class ChangeEmailForm { |
|
|
|
private String oldEmailAddress; |
|
private String newEmailAddress; |
|
|
|
public void setOldEmailAddress(String oldEmailAddress) { |
|
this.oldEmailAddress = oldEmailAddress; |
|
} |
|
|
|
public String getOldEmailAddress() { |
|
return this.oldEmailAddress; |
|
} |
|
|
|
public void setNewEmailAddress(String newEmailAddress) { |
|
this.newEmailAddress = newEmailAddress; |
|
} |
|
|
|
public String getNewEmailAddress() { |
|
return this.newEmailAddress; |
|
} |
|
|
|
} |
|
---- |
|
|
|
Another good practice is to apply |
|
xref:core/validation/beans-beans.adoc#beans-constructor-binding[constructor binding], |
|
which uses only the request parameters it needs for constructor arguments, and any other |
|
input is ignored. This is in contrast to property binding which by default binds every |
|
request parameter for which there is a matching property. |
|
|
|
If neither a dedicated model object nor constructor binding is sufficient, and you must |
|
use property binding, we strongy recommend registering `allowedFields` patterns (case |
|
sensitive) on `WebDataBinder` in order to prevent unexpected properties from being set. |
|
For example: |
|
|
|
[source,java,indent=0,subs="verbatim,quotes"] |
|
---- |
|
@Controller |
|
public class ChangeEmailController { |
|
|
|
@InitBinder |
|
void initBinder(WebDataBinder binder) { |
|
binder.setAllowedFields("oldEmailAddress", "newEmailAddress"); |
|
} |
|
|
|
// @RequestMapping methods, etc. |
|
|
|
} |
|
---- |
|
|
|
You can also register `disallowedFields` patterns (case insensitive). However, |
|
"allowed" configuration is preferred over "disallowed" as it is more explicit and less |
|
prone to mistakes. |
|
|
|
By default, constructor and property binding are both used. If you want to use |
|
constructor binding only, you can set the `declarativeBinding` flag on `WebDataBinder` |
|
through an `@InitBinder` method either locally within a controller or globally through an |
|
`@ControllerAdvice`. Turning this flag on ensures that only constructor binding is used |
|
and that property binding is not used unless `allowedFields` patterns are configured. |
|
For example: |
|
|
|
[source,java,indent=0,subs="verbatim,quotes"] |
|
---- |
|
@Controller |
|
public class MyController { |
|
|
|
@InitBinder |
|
void initBinder(WebDataBinder binder) { |
|
binder.setDeclarativeBinding(true); |
|
} |
|
|
|
// @RequestMapping methods, etc. |
|
|
|
} |
|
----
|
|
|