Skip to content

Commit e244481

Browse files
committed
Merge branch '7.0.x'
2 parents a0ec665 + ca32ac5 commit e244481

6 files changed

Lines changed: 100 additions & 73 deletions

File tree

framework-docs/modules/ROOT/nav.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@
198198
*** xref:web/webmvc/mvc-uri-building.adoc[]
199199
*** xref:web/webmvc/mvc-ann-async.adoc[]
200200
*** xref:web/webmvc/mvc-range.adoc[]
201+
*** xref:web/webmvc/mvc-data-binding.adoc[]
201202
*** xref:web/webmvc-cors.adoc[]
202203
*** xref:web/webmvc-versioning.adoc[]
203204
*** xref:web/webmvc/mvc-ann-rest-exceptions.adoc[]
@@ -295,6 +296,7 @@
295296
*** xref:web/webflux-functional.adoc[]
296297
*** xref:web/webflux/uri-building.adoc[]
297298
*** xref:web/webflux/range.adoc[]
299+
*** xref:web/webflux/data-binding.adoc[]
298300
*** xref:web/webflux-cors.adoc[]
299301
*** xref:web/webflux-versioning.adoc[]
300302
*** xref:web/webflux/ann-rest-exceptions.adoc[]

framework-docs/modules/ROOT/pages/web/webflux/controller/ann-initbinder.adoc

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,4 @@ Kotlin::
107107

108108

109109
[[webflux-ann-initbinder-model-design]]
110-
== Model Design
111-
[.small]#xref:web/webmvc/mvc-controller/ann-initbinder.adoc#mvc-ann-initbinder-model-design[See equivalent in the Servlet stack]#
112-
113-
include::partial$web/web-data-binding-model-design.adoc[]
110+
NOTE: For more guidance on model design, please see xref:web/webflux/data-binding.adoc[Data Binding].
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
[[webflux-data-binding]]
2+
= Data Binding
3+
:page-section-summary-toc: 1
4+
5+
[.small]#xref:web/webmvc/mvc-data-binding.adoc[See equivalent in the Servlet stack]#
6+
7+
Data binding is a mechanism that binds string parameters onto an object graph with type conversion.
8+
It is a core mechanism of the Spring Framework that helps with application configuration.
9+
In web applications it makes it easy to access query parameters and form data through richly typed objects rather than through maps of string values.
10+
11+
To learn more about the data binding mechanism, including constructor and setter binding, property name syntax, type conversion,
12+
and more, see the xref:core/validation/data-binding.adoc[Data binding] in the Core Technologies section.
13+
14+
For annotated controllers, data binding applies to a
15+
xref:web/webflux/controller/ann-methods/modelattrib-method-args.adoc[@ModelAttribute] method argument.
16+
For functional endpoints, use the `bind` method of xref:web/webflux-functional.adoc#webflux-fn-request[ServerRequest].
17+
18+
TIP: For browser applications with annotated controllers, you can use
19+
xref:web/webflux/controller/ann-modelattrib-methods.adoc[@ModelAttribute methods]
20+
to initialize additional model attributes for use in rendered views.
21+
22+
Each request uses a separate `WebDataBinder` instance.
23+
For annotated controllers, this instance can be customized through
24+
xref:web/webflux/controller/ann-initbinder.adoc[@InitBinder methods] within a controller, or
25+
across controllers through xref:web/webmvc/mvc-controller/ann-advice.adoc[Controller Advice].
26+
For functional endpoints, use overloaded `ServerRequest.bind` methods.
27+
28+
29+
30+
31+
[[webflux-data-binding-design]]
32+
== Model Design
33+
[.small]#xref:web/webmvc/mvc-data-binding.adoc#mvc-data-binding-design[See equivalent in the Servlet stack]#
34+
35+
include::partial$web/web-data-binding-model-design.adoc[]
36+

framework-docs/modules/ROOT/pages/web/webmvc/mvc-controller/ann-initbinder.adoc

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,4 @@ Kotlin::
107107

108108

109109
[[mvc-ann-initbinder-model-design]]
110-
== Model Design
111-
[.small]#xref:web/webflux/controller/ann-initbinder.adoc#webflux-ann-initbinder-model-design[See equivalent in the Reactive stack]#
112-
113-
include::partial$web/web-data-binding-model-design.adoc[]
110+
NOTE: For more guidance on model design, please see xref:web/webmvc/mvc-data-binding.adoc[Data Binding].
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[[mvc-data-binding]]
2+
= Data Binding
3+
:page-section-summary-toc: 1
4+
5+
[.small]#xref:web/webflux/data-binding.adoc[See equivalent in the Reactive stack]#
6+
7+
Data binding is a mechanism that binds string parameters onto an object graph with type conversion.
8+
It is a core mechanism of the Spring Framework that helps with application configuration.
9+
In web applications it makes it easy to access query parameters and form data through richly typed objects rather than through maps of string values.
10+
11+
To learn more about the data binding mechanism, including constructor and setter binding, property name syntax, type conversion,
12+
and more, see the xref:core/validation/data-binding.adoc[Data binding] in the Core Technologies section.
13+
14+
For annotated controllers, data binding applies to a
15+
xref:web/webmvc/mvc-controller/ann-methods/modelattrib-method-args.adoc[@ModelAttribute] method argument.
16+
For functional endpoints, use the `bind` method of xref:web/webmvc-functional.adoc#webmvc-fn-request[ServerRequest].
17+
18+
TIP: For browser applications with annotated controllers, you can use
19+
xref:web/webmvc/mvc-controller/ann-modelattrib-methods.adoc[@ModelAttribute methods]
20+
to initialize additional model attributes for use in rendered views.
21+
22+
Each request uses a separate `WebDataBinder` instance.
23+
For annotated controllers, this instance can be customized through
24+
xref:web/webmvc/mvc-controller/ann-initbinder.adoc[@InitBinder methods] within a controller, or
25+
across controllers through xref:web/webmvc/mvc-controller/ann-advice.adoc[Controller Advice].
26+
For functional endpoints, use overloaded `ServerRequest.bind` methods.
27+
28+
29+
30+
[[mvc-data-binding-design]]
31+
== Model Design
32+
[.small]#xref:web/webflux/data-binding.adoc#webflux-data-binding-design[See equivalent in the Reactive stack]#
33+
34+
include::partial$web/web-data-binding-model-design.adoc[]
Lines changed: 26 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,52 @@
1-
xref:core/validation/data-binding.adoc[Data binding] for web requests involves
2-
binding request parameters to a model object. By default, request parameters can be bound
3-
to any public property of the model object, which means malicious clients can provide
4-
extra values for properties that exist in the model object graph, but are not expected to
5-
be set. This is why model object design requires careful consideration.
1+
Data binding involves binding untrusted input onto application objects.
2+
For security reasons, it's crucial to ensure that input is properly constrained to expected fields only.
3+
This section provides guidance for safe binding.
64

7-
TIP: The model object, and its nested object graph is also sometimes referred to as a
8-
_command object_, _form-backing object_, or _POJO_ (Plain Old Java Object).
5+
First, prefer **immutable object design** for web binding purposes.
6+
It is safe because a constructor naturally constrains binding to expected inputs.
7+
You can use a Java record or a class with a primary constructor, and either can have further nested objects.
8+
See xref:core/validation/data-binding.adoc#data-binding-constructor-binding[Constructor Binding] for details.
99

10-
A good practice is to use a _dedicated model object_ rather than exposing your domain
11-
model such as JPA or Hibernate entities for web data binding. For example, on a form to
12-
change an email address, create a `ChangeEmailForm` model object that declares only
13-
the properties required for the input:
10+
Another option for safe binding is to use **dedicated objects** designed for the expected input.
11+
Such objects, even if mutable, are safe because they constrain binding to the expected inputs.
1412

15-
[source,java,indent=0,subs="verbatim,quotes"]
16-
----
17-
public class ChangeEmailForm {
18-
19-
private String oldEmailAddress;
20-
private String newEmailAddress;
21-
22-
public void setOldEmailAddress(String oldEmailAddress) {
23-
this.oldEmailAddress = oldEmailAddress;
24-
}
25-
26-
public String getOldEmailAddress() {
27-
return this.oldEmailAddress;
28-
}
29-
30-
public void setNewEmailAddress(String newEmailAddress) {
31-
this.newEmailAddress = newEmailAddress;
32-
}
33-
34-
public String getNewEmailAddress() {
35-
return this.newEmailAddress;
36-
}
37-
38-
}
39-
----
40-
41-
Another good practice is to apply
42-
xref:core/validation/data-binding.adoc#data-binding-constructor-binding[constructor binding],
43-
which uses only the request parameters it needs for constructor arguments, and any other
44-
input is ignored. This is in contrast to property binding which by default binds every
45-
request parameter for which there is a matching property.
46-
47-
If neither a dedicated model object nor constructor binding is sufficient, and you must
48-
use property binding, we strongly recommend registering `allowedFields` patterns (case
49-
sensitive) on `WebDataBinder` in order to prevent unexpected properties from being set.
13+
Domain objects such as JPA or Hibernate entities are generally not safe for web binding
14+
as they likely contain more properties than the expected inputs.
15+
For such cases, it's crucial to declare the properties to expose for binding.
5016
For example:
5117

5218
[source,java,indent=0,subs="verbatim,quotes"]
5319
----
5420
@Controller
55-
public class ChangeEmailController {
21+
public class PersonController {
5622
5723
@InitBinder
5824
void initBinder(WebDataBinder binder) {
59-
binder.setAllowedFields("oldEmailAddress", "newEmailAddress");
25+
// See Javadoc for supported pattern syntax
26+
binder.setAllowedFields("firstName", "lastName", "*Address");
6027
}
61-
62-
// @RequestMapping methods, etc.
63-
6428
}
6529
----
6630

67-
You can also register `disallowedFields` patterns (case insensitive). However,
68-
"allowed" configuration is preferred over "disallowed" as it is more explicit and less
69-
prone to mistakes.
31+
NOTE: It is also possible to configure `disallowedFields`, but that's fragile, and
32+
due to be https://github.com/spring-projects/spring-framework/issues/36802[deprecated] in Spring Framework 7.1.
33+
It is easy to miss or add others over time that should also be excluded.
7034

71-
By default, constructor and property binding are both used. If you want to use
72-
constructor binding only, you can set the `declarativeBinding` flag on `WebDataBinder`
73-
through an `@InitBinder` method either locally within a controller or globally through an
74-
`@ControllerAdvice`. Turning this flag on ensures that only constructor binding is used
75-
and that property binding is not used unless `allowedFields` patterns are configured.
76-
For example:
35+
By default, `DataBinder` applies both constructor and setter binding.
36+
This is fine with immutable objects and dedicated objects, but for domain objects, you must
37+
remember to declare `allowFields`. To ensure data binding is only used in declarative style where
38+
expected inputs are explicitly declared, you can set `declarativeBinding=true` on `DataBinder`.
39+
In this mode, `DataBinding` applies constructor binding, and additionally setter binding if `allowedFields` is set.
40+
The below shows how to set this flag globally:
7741

7842
[source,java,indent=0,subs="verbatim,quotes"]
7943
----
80-
@Controller
81-
public class MyController {
44+
@ControllerAdvice
45+
public class ControllerConfig {
8246
8347
@InitBinder
8448
void initBinder(WebDataBinder binder) {
8549
binder.setDeclarativeBinding(true);
8650
}
87-
88-
// @RequestMapping methods, etc.
89-
9051
}
9152
----

0 commit comments

Comments
 (0)