我正在使用Spring 3.2.0。我已经为一些基本需求注册了一些自定义属性编辑器,如下所示。
import editors.DateTimeEditor;
import editors.StrictNumberFormatEditor;
import java.math.RoundingMode;
import java.net.URL;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import org.joda.time.DateTime;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.beans.propertyeditors.URLEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.context.request.WebRequest;
@ControllerAdvice
public final class GlobalDataBinder
{
@InitBinder
public void initBinder(WebDataBinder binder, WebRequest request)
{
binder.setIgnoreInvalidFields(true);
binder.setIgnoreUnknownFields(true);
//binder.setAllowedFields(someArray);
NumberFormat numberFormat=DecimalFormat.getInstance();
numberFormat.setGroupingUsed(false);
numberFormat.setMaximumFractionDigits(2);
numberFormat.setRoundingMode(RoundingMode.HALF_UP);
binder.registerCustomEditor(DateTime.class, new DateTimeEditor("MM/dd/yyyy HH:mm:ss", true));
binder.registerCustomEditor(Double.class, new StrictNumberFormatEditor(Double.class, numberFormat, true));
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
binder.registerCustomEditor(URL.class, new URLEditor());
}
}
到目前为止,我已经注册了这么多编辑。其中两个DateTimeEditor
和StrictNumberFormatEditor
已通过覆盖相应方法进行自定义,以满足数字格式和Joda-Time的自定义需求。
由于我使用的是Spring 3.2.0,我可以利用@ControllerAdvice
。
Spring建议使用setAllowedFields()
方法列出一组允许的字段,以便恶意用户无法将值注入绑定对象。
来自docs关于DataBinder
允许将属性值设置到目标对象上的Binder, 包括对验证和绑定结果分析的支持。该 绑定过程可以通过指定允许的字段来定制, 必填字段,自定义编辑器等
请注意,未能设置可能会对安全产生影响 一系列允许的字段。在HTTP表单POST数据的情况下 例如,恶意客户端可以尝试通过破坏应用程序 提供不存在的字段或属性的值 形成。在某些情况下,这可能导致非法数据被设置 命令对象或其嵌套对象。因此,它非常强烈 建议在DataBinder上指定
allowedFields
属性。
我有一个很大的应用程序,显然有数千个字段。使用setAllowedFields()
指定和列出所有这些是一项繁琐的工作。另外,不知怎的,我需要记住它们。
根据需要更改网页以删除某些字段或添加其他字段需要修改setAllowedFields()
方法的参数值以反映这些更改。
还有其他选择吗?
答案 0 :(得分:4)
您可以使用setAllowedFields()
黑名单,而不是使用setDisallowedFields()
白名单。例如,来自petclinic样本申请:
@InitBinder
public void setAllowedFields(WebDataBinder dataBinder) {
dataBinder.setDisallowedFields("id");
}
从纯粹的安全角度来看,白名单比黑名单更受欢迎,但它可能有助于减轻一些负担。
答案 1 :(得分:2)
在Web层中直接使用实体对象时,setAllowedFields()非常方便。或者,可以使用专用数据传输对象(DTO),在服务层中构造实体对象。工厂不仅可以重复使用,而且还可以在网络环境之外使用,例如,用于异步消息。此外,DTO继承不必遵循实体继承,因此您可以根据用例的需要自由设计DTO层次结构。
答案 2 :(得分:0)
4.9。明确指定绑定
使用binder元素配置视图可用的确切模型绑定集。这在Spring MVC环境中特别有用,用于限制每个视图的“允许字段”集。
<view-state id="enterBookingDetails" model="booking">
<binder>
<binding property="creditCard" />
<binding property="creditCardName" />
<binding property="creditCardExpiryMonth" />
<binding property="creditCardExpiryYear" />
</binder>
<transition on="proceed" to="reviewBooking" />
<transition on="cancel" to="cancel" bind="false" />
</view-state>
如果未指定binder元素,则模型的所有公共属性都有资格通过视图进行绑定。指定了binder元素后,只允许显式配置的绑定。
每个绑定还可以应用转换器来格式化模型属性值,以便以自定义方式显示。如果未指定转换器,则将使用模型属性类型的默认转换器。
<view-state id="enterBookingDetails" model="booking">
<binder>
<binding property="checkinDate" converter="shortDate" />
<binding property="checkoutDate" converter="shortDate" />
<binding property="creditCard" />
<binding property="creditCardName" />
<binding property="creditCardExpiryMonth" />
<binding property="creditCardExpiryYear" />
</binder>
<transition on="proceed" to="reviewBooking" />
<transition on="cancel" to="cancel" bind="false" />
</view-state>
在上面的示例中,shortDate转换器绑定到checkinDate和checkoutDate属性。自定义转换器可以在应用程序的ConversionService中注册。
如果用户提供的值在表单回发时为null,则每个绑定也可能会应用必需的检查,这将生成验证错误:
<view-state id="enterBookingDetails" model="booking">
<binder>
<binding property="checkinDate" converter="shortDate" required="true" />
<binding property="checkoutDate" converter="shortDate" required="true" />
<binding property="creditCard" required="true" />
<binding property="creditCardName" required="true" />
<binding property="creditCardExpiryMonth" required="true" />
<binding property="creditCardExpiryYear" required="true" />
</binder>
<transition on="proceed" to="reviewBooking">
<transition on="cancel" to="bookingCancelled" bind="false" />
</view-state>
在上面的示例中,所有绑定都是必需的。如果绑定了一个或多个空白输入值,则将生成验证错误,并且视图将使用这些错误重新呈现。
答案 3 :(得分:0)
一种将活页夹与DTO结合使用的解决方案(例如,companydata),以防大多数表单输入值如果为空则应转换为null,但是需要添加一些例外(setDisallowedFields对我不起作用)。
@InitBinder()
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
}
@InitBinder
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) {
binder.registerCustomEditor(String.class, "companydata.companyName", new StringTrimmerEditor(false));
binder.registerCustomEditor(String.class, "companydata.companyNumber", new StringTrimmerEditor(false));
}