|
对于最新的稳定版本,请使用 Spring Framework 7.0.6! |
DataBinder
@Controller 或 @ControllerAdvice 个类可以有 @InitBinder 个方法来初始化 WebDataBinder 的实例,这些方法反过来可以:
-
将请求参数(即表单或查询数据)绑定到模型对象。
-
将基于字符串的请求值(例如请求参数、路径变量、标头、cookie 等)转换为目标类型的控制器方法参数。
-
Format model object values as
Stringvalues when rendering HTML forms.
@InitBinder 方法可以注册控制器特定的 java.beans.PropertyEditor 或
Spring Converter 和 Formatter 组件。此外,您可以使用
MVC 配置 来在全局共享的 FormattingConversionService 中注册 Converter 和 Formatter
类型。
@InitBinder 方法支持许多与 @RequestMapping 方法相同的参数,但不包括 @ModelAttribute(命令对象)参数。通常,它们声明为具有 WebDataBinder 参数(用于注册)和 void 返回值。以下示例显示了一个示例:
-
Java
-
Kotlin
@Controller
public class FormController {
@InitBinder (1)
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}
// ...
}
| 1 | 定义一个@InitBinder方法。 |
@Controller
class FormController {
@InitBinder (1)
fun initBinder(binder: WebDataBinder) {
val dateFormat = SimpleDateFormat("yyyy-MM-dd")
dateFormat.isLenient = false
binder.registerCustomEditor(Date::class.java, CustomDateEditor(dateFormat, false))
}
// ...
}
| 1 | 定义一个@InitBinder方法。 |
Alternatively, when you use a Formatter-based setup through a shared
FormattingConversionService, you can re-use the same approach and register
controller-specific Formatter implementations, as the following example shows:
-
Java
-
Kotlin
@Controller
public class FormController {
@InitBinder (1)
protected void initBinder(WebDataBinder binder) {
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
}
// ...
}
| 1 | 在自定义格式化器上定义一个@InitBinder方法。 |
@Controller
class FormController {
@InitBinder (1)
protected fun initBinder(binder: WebDataBinder) {
binder.addCustomFormatter(DateFormatter("yyyy-MM-dd"))
}
// ...
}
| 1 | 在自定义格式化器上定义一个@InitBinder方法。 |
模型设计
在Web应用程序的上下文中,数据绑定涉及将HTTP请求参数(即表单数据或查询参数)绑定到模型对象及其嵌套对象的属性。
仅 public 个属性遵循
JavaBeans命名约定
并公开用于数据绑定 —— 例如,public String getFirstName() 和
public void setFirstName(String) 方法用于 firstName 属性。
| 模型对象及其嵌套的对象图有时也被称为命令对象、表单支持对象或POJO(简单的Java对象)。 |
默认情况下,Spring 允许绑定到模型对象图中的所有公共属性。这意味着你需要仔细考虑模型有哪些公共属性,因为客户端可能会针对任何公共属性路径进行操作,甚至包括那些在特定使用场景下不期望被操作的属性。
例如,给定一个HTTP表单数据端点,恶意客户端可能会提供模型对象图中存在的属性值,但这些属性并不包含在浏览器中显示的HTML表单中。这可能会导致数据被设置在模型对象及其任何嵌套对象上,而这些数据是不期望被更新的。
推荐的做法是使用一个专用的模型对象,该对象仅公开与表单提交相关的属性。例如,在用于更改用户电子邮件地址的表单中,模型对象应声明一组最小的属性,如以下ChangeEmailForm所示。
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;
}
}
如果你不能或不想为每个数据绑定用例使用一个专用的模型对象,你必须限制允许进行数据绑定的属性。理想情况下,你可以通过在WebDataBinder上使用setAllowedFields()方法来注册允许的字段模式。
例如,要在应用程序中注册允许的字段模式,您可以在@InitBinder方法中实现一个@Controller或@ControllerAdvice组件,如下所示:
@Controller
public class ChangeEmailController {
@InitBinder
void initBinder(WebDataBinder binder) {
binder.setAllowedFields("oldEmailAddress", "newEmailAddress");
}
// @RequestMapping methods, etc.
}
除了注册允许的模式外,还可以通过setDisallowedFields()方法在DataBinder及其子类中注册不允许的字段模式。请注意,“白名单”比“黑名单”更安全。因此,建议优先使用setAllowedFields()而不是setDisallowedFields()。
请注意,与允许的字段模式匹配是区分大小写的;而与不允许的字段模式匹配是不区分大小写的。此外,即使某个字段也恰好匹配允许列表中的模式,但如果它匹配了不允许的模式,该字段也不会被接受。
|
正确配置允许和不允许的字段模式非常重要,尤其是在直接暴露领域模型以进行数据绑定时。否则,这将是一个很大的安全风险。 此外,强烈建议您不要在数据绑定场景中使用来自领域模型(如JPA或Hibernate实体)的类型作为模型对象。 |