From 667eb42a6329cb8f7c519bf4dd415d3ca9540628 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Tue, 1 Aug 2023 07:50:06 +0300 Subject: [PATCH] Polishing See gh-30952 --- .../webflux/controller/ann-initbinder.adoc | 27 ++-- .../ann-methods/modelattrib-method-args.adoc | 131 ++++++++-------- .../webmvc/mvc-controller/ann-initbinder.adoc | 30 ++-- .../ann-methods/modelattrib-method-args.adoc | 142 ++++++++---------- .../web/web-data-binding-model-design.adoc | 65 ++------ 5 files changed, 176 insertions(+), 219 deletions(-) diff --git a/framework-docs/modules/ROOT/pages/web/webflux/controller/ann-initbinder.adoc b/framework-docs/modules/ROOT/pages/web/webflux/controller/ann-initbinder.adoc index 320d56b3ca..3893881ea4 100644 --- a/framework-docs/modules/ROOT/pages/web/webflux/controller/ann-initbinder.adoc +++ b/framework-docs/modules/ROOT/pages/web/webflux/controller/ann-initbinder.adoc @@ -3,23 +3,21 @@ [.small]#xref:web/webmvc/mvc-controller/ann-initbinder.adoc[See equivalent in the Servlet stack]# -`@Controller` or `@ControllerAdvice` classes can have `@InitBinder` methods, to -initialize instances of `WebDataBinder`. Those, in turn, are used to: +`@Controller` or `@ControllerAdvice` classes can have `@InitBinder` methods to +initialize `WebDataBinder` instances that in turn can: -* Bind request parameters (that is, form data or query) to a model object. -* Convert `String`-based request values (such as request parameters, path variables, -headers, cookies, and others) to the target type of controller method arguments. -* Format model object values as `String` values when rendering HTML forms. +* Bind request parameters to a model object. +* Convert request values from string to object property types. +* Format model object properties as strings when rendering HTML forms. -`@InitBinder` methods can register controller-specific `java.beans.PropertyEditor` or -Spring `Converter` and `Formatter` components. In addition, you can use the -xref:web/webflux/config.adoc#webflux-config-conversion[WebFlux Java configuration] to register `Converter` and -`Formatter` types in a globally shared `FormattingConversionService`. +In an `@Controller`, `DataBinder` customizations apply locally within the controller, +or even to a specific model attribute referenced by name through the annotation. +In an `@ControllerAdvice` customizations can apply to all or a subset of controllers. -`@InitBinder` methods support many of the same arguments that `@RequestMapping` methods -do, except for `@ModelAttribute` (command object) arguments. Typically, they are declared -with a `WebDataBinder` argument, for registrations, and a `void` return value. -The following example uses the `@InitBinder` annotation: +You can register `PropertyEditor`, `Converter`, and `Formatter` components in the +`DataBinder` for type conversion. Alternatively, you can use the +xref:web/webflux/config.adoc#webflux-config-conversion[WebFlux config] to register +`Converter` and `Formatter` components in a globally shared `FormattingConversionService`. -- [tabs] @@ -112,4 +110,5 @@ Kotlin:: == Model Design [.small]#xref:web/webmvc/mvc-controller/ann-initbinder.adoc#mvc-ann-initbinder-model-design[See equivalent in the Servlet stack]# +include::partial$web/web-data-binding-model-design.adoc[] diff --git a/framework-docs/modules/ROOT/pages/web/webflux/controller/ann-methods/modelattrib-method-args.adoc b/framework-docs/modules/ROOT/pages/web/webflux/controller/ann-methods/modelattrib-method-args.adoc index 809104fe1e..48353d675d 100644 --- a/framework-docs/modules/ROOT/pages/web/webflux/controller/ann-methods/modelattrib-method-args.adoc +++ b/framework-docs/modules/ROOT/pages/web/webflux/controller/ann-methods/modelattrib-method-args.adoc @@ -3,11 +3,8 @@ [.small]#xref:web/webmvc/mvc-controller/ann-methods/modelattrib-method-args.adoc[See equivalent in the Servlet stack]# -You can use the `@ModelAttribute` annotation on a method argument to access an attribute from the -model or have it instantiated if not present. The model attribute is also overlaid with -the values of query parameters and form fields whose names match to field names. This is -referred to as data binding, and it saves you from having to deal with parsing and -converting individual query parameters and form fields. The following example binds an instance of `Pet`: +The `@ModelAttribute` method parameter annotation binds request parameters onto a model +object. For example: [tabs] ====== @@ -18,7 +15,7 @@ Java:: @PostMapping("/owners/{ownerId}/pets/{petId}/edit") public String processSubmit(@ModelAttribute Pet pet) { } // <1> ---- -<1> Bind an instance of `Pet`. +<1> Bind to an instance of `Pet`. Kotlin:: + @@ -27,28 +24,34 @@ Kotlin:: @PostMapping("/owners/{ownerId}/pets/{petId}/edit") fun processSubmit(@ModelAttribute pet: Pet): String { } // <1> ---- -<1> Bind an instance of `Pet`. +<1> Bind to an instance of `Pet`. ====== -The `Pet` instance in the preceding example is resolved as follows: +The `Pet` instance may be: -* From the model if already added through xref:web/webflux/controller/ann-modelattrib-methods.adoc[`Model`]. -* From the HTTP session through xref:web/webflux/controller/ann-methods/sessionattributes.adoc[`@SessionAttributes`]. -* From the invocation of a default constructor. -* From the invocation of a "`primary constructor`" with arguments that match query -parameters or form fields. Argument names are determined through JavaBeans -`@ConstructorProperties` or through runtime-retained parameter names in the bytecode. +* Accessed from the model where it could have been added by a + xref:web/webflux/controller/ann-modelattrib-methods.adoc[`Model`]. +* Accessed from the HTTP session if the model attribute was listed in + the class-level xref:web/webflux/controller/ann-methods/sessionattributes.adoc[`@SessionAttributes`]. +* Instantiated through a default constructor. +* Instantiated through a "`primary constructor`" with arguments that match to Servlet +request parameters. Argument names are determined through runtime-retained parameter +names in the bytecode. -After the model attribute instance is obtained, data binding is applied. The -`WebExchangeDataBinder` class matches names of query parameters and form fields to field -names on the target `Object`. Matching fields are populated after type conversion is applied -where necessary. For more on data binding (and validation), see -xref:web/webmvc/mvc-config/validation.adoc[Validation]. For more on customizing data binding, see -xref:web/webflux/controller/ann-initbinder.adoc[`DataBinder`]. +Once a model attribute instance is available, `WebDataBinder` binds request parameters to +properties of the target `Object` with type conversion where necessary. +For more on data binding and validation, see +xref:web/webmvc/mvc-config/validation.adoc[Validation]. +For more on customizing data binding, see +xref:web/webmvc/mvc-controller/ann-initbinder.adoc[DataBinder]. -Data binding can result in errors. By default, a `WebExchangeBindException` is raised, but, -to check for such errors in the controller method, you can add a `BindingResult` argument -immediately next to the `@ModelAttribute`, as the following example shows: +WebFlux, unlike Spring MVC, supports reactive types in the model, e.g. `Mono`. +You can declare a `@ModelAttribute` argument with or without a reactive type wrapper, and +it will be resolved accordingly to the actual value. + +If data binding results in errors, by default a `WebExchangeBindException` is raised, +but you can also add a `BindingResult` argument immediately next to the `@ModelAttribute` +in order to handle such errors in the controller method. For example: [tabs] ====== @@ -81,49 +84,9 @@ Kotlin:: <1> Adding a `BindingResult`. ====== -You can automatically apply validation after data binding by adding the -`jakarta.validation.Valid` annotation or Spring's `@Validated` annotation (see also -xref:core/validation/beanvalidation.adoc[Bean Validation] and -xref:web/webmvc/mvc-config/validation.adoc[Spring validation]). The following example uses the `@Valid` annotation: - -[tabs] -====== -Java:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="primary"] ----- - @PostMapping("/owners/{ownerId}/pets/{petId}/edit") - public String processSubmit(@Valid @ModelAttribute("pet") Pet pet, BindingResult result) { // <1> - if (result.hasErrors()) { - return "petForm"; - } - // ... - } ----- -<1> Using `@Valid` on a model attribute argument. - -Kotlin:: -+ -[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] ----- - @PostMapping("/owners/{ownerId}/pets/{petId}/edit") - fun processSubmit(@Valid @ModelAttribute("pet") pet: Pet, result: BindingResult): String { // <1> - if (result.hasErrors()) { - return "petForm" - } - // ... - } ----- -<1> Using `@Valid` on a model attribute argument. -====== - -Spring WebFlux, unlike Spring MVC, supports reactive types in the model -- for example, -`Mono` or `io.reactivex.Single`. You can declare a `@ModelAttribute` argument -with or without a reactive type wrapper, and it will be resolved accordingly, -to the actual value if necessary. However, note that, to use a `BindingResult` -argument, you must declare the `@ModelAttribute` argument before it without a reactive -type wrapper, as shown earlier. Alternatively, you can handle any errors through the -reactive type, as the following example shows: +To use a `BindingResult` argument, you must declare the `@ModelAttribute` argument before +it without a reactive type wrapper. If you want to use the reactive, you can handle errors +directly through it. For example: [tabs] ====== @@ -160,6 +123,42 @@ Kotlin:: ---- ====== +You can automatically apply validation after data binding by adding the +`jakarta.validation.Valid` annotation or Spring's `@Validated` annotation (see +xref:core/validation/beanvalidation.adoc[Bean Validation] and +xref:web/webmvc/mvc-config/validation.adoc[Spring validation]). For example: + +[tabs] +====== +Java:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +---- + @PostMapping("/owners/{ownerId}/pets/{petId}/edit") + public String processSubmit(@Valid @ModelAttribute("pet") Pet pet, BindingResult result) { // <1> + if (result.hasErrors()) { + return "petForm"; + } + // ... + } +---- +<1> Using `@Valid` on a model attribute argument. + +Kotlin:: ++ +[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] +---- + @PostMapping("/owners/{ownerId}/pets/{petId}/edit") + fun processSubmit(@Valid @ModelAttribute("pet") pet: Pet, result: BindingResult): String { // <1> + if (result.hasErrors()) { + return "petForm" + } + // ... + } +---- +<1> Using `@Valid` on a model attribute argument. +====== + If method validation applies because other parameters have `@Constraint` annotations, then `HandlerMethodValidationException` would be raised instead. See the section on controller method xref:web/webmvc/mvc-controller/ann-validation.adoc[Validation]. diff --git a/framework-docs/modules/ROOT/pages/web/webmvc/mvc-controller/ann-initbinder.adoc b/framework-docs/modules/ROOT/pages/web/webmvc/mvc-controller/ann-initbinder.adoc index 7507980ae1..f2dd158dc4 100644 --- a/framework-docs/modules/ROOT/pages/web/webmvc/mvc-controller/ann-initbinder.adoc +++ b/framework-docs/modules/ROOT/pages/web/webmvc/mvc-controller/ann-initbinder.adoc @@ -3,23 +3,25 @@ [.small]#xref:web/webflux/controller/ann-initbinder.adoc[See equivalent in the Reactive stack]# -`@Controller` or `@ControllerAdvice` classes can have `@InitBinder` methods that -initialize instances of `WebDataBinder`, and those, in turn, can: +`@Controller` or `@ControllerAdvice` classes can have `@InitBinder` methods to +initialize `WebDataBinder` instances that in turn can: -* Bind request parameters (that is, form or query data) to a model object. -* Convert String-based request values (such as request parameters, path variables, -headers, cookies, and others) to the target type of controller method arguments. -* Format model object values as `String` values when rendering HTML forms. +* Bind request parameters to a model object. +* Convert request values from string to object property types. +* Format model object properties as strings when rendering HTML forms. -`@InitBinder` methods can register controller-specific `java.beans.PropertyEditor` or -Spring `Converter` and `Formatter` components. In addition, you can use the -xref:web/webmvc/mvc-config/conversion.adoc[MVC config] to register `Converter` and `Formatter` -types in a globally shared `FormattingConversionService`. +In an `@Controller`, `DataBinder` customizations apply locally within the controller, +or even to a specific model attribute referenced by name through the annotation. +In an `@ControllerAdvice` customizations can apply to all or a subset of controllers. -`@InitBinder` methods support many of the same arguments that `@RequestMapping` methods -do, except for `@ModelAttribute` (command object) arguments. Typically, they are declared -with a `WebDataBinder` argument (for registrations) and a `void` return value. -The following listing shows an example: +You can register `PropertyEditor`, `Converter`, and `Formatter` components in the +`DataBinder` for type conversion. Alternatively, you can use the +xref:web/webmvc/mvc-config/conversion.adoc[MVC config] to register `Converter` and +`Formatter` components in a globally shared `FormattingConversionService`. + +`@InitBinder` methods can have many of the same arguments that `@RequestMapping` methods +have, with the notable exception of `@ModelAttribute`. Typically, such methods have a +`WebDataBinder` argument (for registrations) and a `void` return value, for example: [tabs] ====== diff --git a/framework-docs/modules/ROOT/pages/web/webmvc/mvc-controller/ann-methods/modelattrib-method-args.adoc b/framework-docs/modules/ROOT/pages/web/webmvc/mvc-controller/ann-methods/modelattrib-method-args.adoc index 1add700c9e..f7af5f1f53 100644 --- a/framework-docs/modules/ROOT/pages/web/webmvc/mvc-controller/ann-methods/modelattrib-method-args.adoc +++ b/framework-docs/modules/ROOT/pages/web/webmvc/mvc-controller/ann-methods/modelattrib-method-args.adoc @@ -3,11 +3,8 @@ [.small]#xref:web/webflux/controller/ann-methods/modelattrib-method-args.adoc[See equivalent in the Reactive stack]# -You can use the `@ModelAttribute` annotation on a method argument to access an attribute from -the model or have it be instantiated if not present. The model attribute is also overlain with -values from HTTP Servlet request parameters whose names match to field names. This is referred -to as data binding, and it saves you from having to deal with parsing and converting individual -query parameters and form fields. The following example shows how to do so: +The `@ModelAttribute` method parameter annotation binds request parameters onto a model +object. For example: [tabs] ====== @@ -20,7 +17,7 @@ Java:: // method logic... } ---- -<1> Bind an instance of `Pet`. +<1> Bind to an instance of `Pet`. Kotlin:: + @@ -31,30 +28,27 @@ fun processSubmit(@ModelAttribute pet: Pet): String { // <1> // method logic... } ---- -<1> Bind an instance of `Pet`. +<1> Bind to an instance of `Pet`. ====== -The `Pet` instance above is sourced in one of the following ways: +The `Pet` instance may be: -* Retrieved from the model where it may have been added by a +* Accessed from the model where it could have been added by a xref:web/webmvc/mvc-controller/ann-modelattrib-methods.adoc[@ModelAttribute method]. -* Retrieved from the HTTP session if the model attribute was listed in +* Accessed from the HTTP session if the model attribute was listed in the class-level xref:web/webmvc/mvc-controller/ann-methods/sessionattributes.adoc[`@SessionAttributes`] annotation. -* Obtained through a `Converter` where the model attribute name matches the name of a - request value such as a path variable or a request parameter (see next example). -* Instantiated using its default constructor. +* Obtained through a `Converter` if the model attribute name matches the name of a + request value such as a path variable or a request parameter (example follows). +* Instantiated through a default constructor. * Instantiated through a "`primary constructor`" with arguments that match to Servlet - request parameters. Argument names are determined through JavaBeans - `@ConstructorProperties` or through runtime-retained parameter names in the bytecode. + request parameters. Argument names are determined through runtime-retained parameter + names in the bytecode. -One alternative to using a xref:web/webmvc/mvc-controller/ann-modelattrib-methods.adoc[@ModelAttribute method] to -supply it or relying on the framework to create the model attribute, is to have a -`Converter` to provide the instance. This is applied when the model attribute -name matches to the name of a request value such as a path variable or a request -parameter, and there is a `Converter` from `String` to the model attribute type. -In the following example, the model attribute name is `account` which matches the URI -path variable `account`, and there is a registered `Converter` which -could load the `Account` from a data store: +As mentioned above, a `Converter` may be used to obtain the model object if +the model attribute name matches to the name of a request value such as a path variable or a +request parameter, _and_ there is a compatible `Converter`. In the below example, +the model attribute name `account` matches URI path variable `account`, and there is a +registered `Converter` that perhaps retrieves it from a persistence store: [tabs] ====== @@ -67,7 +61,6 @@ Java:: // ... } ---- -<1> Bind an instance of `Account` using an explicit attribute name. Kotlin:: + @@ -78,50 +71,14 @@ Kotlin:: // ... } ---- -<1> Bind an instance of `Account` using an explicit attribute name. ====== -After the model attribute instance is obtained, data binding is applied. The -`WebDataBinder` class matches Servlet request parameter names (query parameters and form -fields) to field names on the target `Object`. Matching fields are populated after type -conversion is applied, where necessary. For more on data binding (and validation), see -xref:web/webmvc/mvc-config/validation.adoc[Validation]. For more on customizing data binding, see -xref:web/webmvc/mvc-controller/ann-initbinder.adoc[`DataBinder`]. - -Data binding can result in errors. By default, a `BindException` is raised. However, to check -for such errors in the controller method, you can add a `BindingResult` argument immediately next -to the `@ModelAttribute`, as the following example shows: - -[tabs] -====== -Java:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="primary"] ----- - @PostMapping("/owners/{ownerId}/pets/{petId}/edit") - public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result) { // <1> - if (result.hasErrors()) { - return "petForm"; - } - // ... - } ----- -<1> Adding a `BindingResult` next to the `@ModelAttribute`. - -Kotlin:: -+ -[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] ----- - @PostMapping("/owners/{ownerId}/pets/{petId}/edit") - fun processSubmit(@ModelAttribute("pet") pet: Pet, result: BindingResult): String { // <1> - if (result.hasErrors()) { - return "petForm" - } - // ... - } ----- -<1> Adding a `BindingResult` next to the `@ModelAttribute`. -====== +Once a model attribute instance is available, `WebDataBinder` binds request parameters to +properties of the target `Object` with type conversion where necessary. +For more on data binding and validation, see +xref:web/webmvc/mvc-config/validation.adoc[Validation]. +For more on customizing data binding, see +xref:web/webmvc/mvc-controller/ann-initbinder.adoc[DataBinder]. In some cases, you may want access to a model attribute without data binding. For such cases, you can inject the `Model` into the controller and access it directly or, @@ -171,13 +128,48 @@ Kotlin:: // ... } ---- -<1> Setting `@ModelAttribute(binding=false)`. +<1> Setting `@ModelAt\tribute(binding=false)`. +====== + +If data binding results in errors, by default a `MethodArgumentNotValidException` is raised, +but you can also add a `BindingResult` argument immediately next to the `@ModelAttribute` +in order to handle such errors in the controller method. For example: + +[tabs] +====== +Java:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +---- + @PostMapping("/owners/{ownerId}/pets/{petId}/edit") + public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result) { // <1> + if (result.hasErrors()) { + return "petForm"; + } + // ... + } +---- +<1> Adding a `BindingResult` next to the `@ModelAttribute`. + +Kotlin:: ++ +[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] +---- + @PostMapping("/owners/{ownerId}/pets/{petId}/edit") + fun processSubmit(@ModelAttribute("pet") pet: Pet, result: BindingResult): String { // <1> + if (result.hasErrors()) { + return "petForm" + } + // ... + } +---- +<1> Adding a `BindingResult` next to the `@ModelAttribute`. ====== You can automatically apply validation after data binding by adding the -`jakarta.validation.Valid` annotation or Spring's `@Validated` annotation -(xref:core/validation/beanvalidation.adoc[Bean Validation] and -xref:web/webmvc/mvc-config/validation.adoc[Spring validation]). The following example shows how to do so: +`jakarta.validation.Valid` annotation or Spring's `@Validated` annotation. +See xref:core/validation/beanvalidation.adoc[Bean Validation] and +xref:web/webmvc/mvc-config/validation.adoc[Spring validation]. For example: [tabs] ====== @@ -210,15 +202,13 @@ Kotlin:: <1> Validate the `Pet` instance. ====== -If an `@ModelAttribute` is declared without `BindingResult` parameter after it, then -`MethodArgumentNotValueException` is raised. However, if method validation applies because -other parameters have `@Constraint` annotations, then `HandlerMethodValidationException` -is raised instead. For more details, see the section on +If there is no `BindingResult` parameter after the `@ModelAttribute`, then +`MethodArgumentNotValueException` is raised with the validation errors. However, if method +validation applies because other parameters have `@jakarta.validation.Constraint` annotations, +then `HandlerMethodValidationException` is raised instead. For more details, see the section xref:web/webmvc/mvc-controller/ann-validation.adoc[Validation]. TIP: Using `@ModelAttribute` is optional. By default, any parameter that is not a simple value type as determined by {api-spring-framework}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty] _AND_ that is not resolved by any other argument resolver is treated as an `@ModelAttribute`. - - diff --git a/framework-docs/modules/ROOT/partials/web/web-data-binding-model-design.adoc b/framework-docs/modules/ROOT/partials/web/web-data-binding-model-design.adoc index 352e63d3c6..66894cec12 100644 --- a/framework-docs/modules/ROOT/partials/web/web-data-binding-model-design.adoc +++ b/framework-docs/modules/ROOT/partials/web/web-data-binding-model-design.adoc @@ -1,29 +1,16 @@ -In the context of web applications, _data binding_ involves the binding of HTTP request -parameters (that is, form data or query parameters) to properties in a model object and -its nested objects. +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. -Only `public` properties following the -https://www.oracle.com/java/technologies/javase/javabeans-spec.html[JavaBeans naming conventions] -are exposed for data binding — for example, `public String getFirstName()` and -`public void setFirstName(String)` methods for a `firstName` property. - -TIP: The model object, and its nested object graph, is also sometimes referred to as a +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). -By default, Spring permits binding to all public properties in the model object graph. -This means you need to carefully consider what public properties the model has, since a -client could target any public property path, even some that are not expected to be -targeted for a given use case. - -For example, given an HTTP form data endpoint, a malicious client could supply values for -properties that exist in the model object graph but are not part of the HTML form -presented in the browser. This could lead to data being set on the model object and any -of its nested objects, that is not expected to be updated. - -The recommended approach is to use a _dedicated model object_ that exposes only -properties that are relevant for the form submission. For example, on a form for changing -a user's email address, the model object should declare a minimum set of properties such -as in the following `ChangeEmailForm`. +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"] ---- @@ -51,13 +38,9 @@ as in the following `ChangeEmailForm`. } ---- -If you cannot or do not want to use a _dedicated model object_ for each data -binding use case, you **must** limit the properties that are allowed for data binding. -Ideally, you can achieve this by registering _allowed field patterns_ via the -`setAllowedFields()` method on `WebDataBinder`. - -For example, to register allowed field patterns in your application, you can implement an -`@InitBinder` method in a `@Controller` or `@ControllerAdvice` component as shown below: +If a dedicated model object is not feasible, we strongy recommend registering +`allowedFields` patterns (case sensitive) on `WebDataBinder` in order to prevent other +properties from being set. For example: [source,java,indent=0,subs="verbatim,quotes"] ---- @@ -74,22 +57,6 @@ For example, to register allowed field patterns in your application, you can imp } ---- -In addition to registering allowed patterns, it is also possible to register _disallowed -field patterns_ via the `setDisallowedFields()` method in `DataBinder` and its subclasses. -Please note, however, that an "allow list" is safer than a "deny list". Consequently, -`setAllowedFields()` should be favored over `setDisallowedFields()`. - -Note that matching against allowed field patterns is case-sensitive; whereas, matching -against disallowed field patterns is case-insensitive. In addition, a field matching a -disallowed pattern will not be accepted even if it also happens to match a pattern in the -allowed list. - -[WARNING] -==== -It is extremely important to properly configure allowed and disallowed field patterns -when exposing your domain model directly for data binding purposes. Otherwise, it is a -big security risk. - -Furthermore, it is strongly recommended that you do **not** use types from your domain -model such as JPA or Hibernate entities as the model object in data binding scenarios. -==== +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.