2

我正在使用 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()以便恶意用户无法将值注入绑定对象。

关于_DataBinder

允许在目标对象上设置属性值的绑定器,包括对验证和绑定结果分析的支持。可以通过指定允许字段、必填字段、自定义编辑器等来自定义绑定过程。

请注意,未能设置允许的字段数组可能会带来安全隐患。例如,在 HTTP 表单 POST 数据的情况下,恶意客户端可以尝试通过提供表单上不存在的字段或属性的值来破坏应用程序。在某些情况下,这可能会导致在命令对象或其嵌套对象上设置非法数据。因此,强烈建议allowedFields在 DataBinder 上指定属性。


我有一个很大的应用程序,显然有数千个领域。用 指定和列出所有这些setAllowedFields()是一项乏味的工作。此外,不知何故我需要记住它们。

根据需要更改网页以删除某些字段或添加其他字段需要修改setAllowedFields()方法的参数值以反映这些更改。

有没有其他选择?

4

4 回答 4

4

setAllowedFields()您可以使用黑名单,而不是使用白setDisallowedFields()名单。例如,来自 petclinic 示例应用程序:

@InitBinder
public void setAllowedFields(WebDataBinder dataBinder) {
    dataBinder.setDisallowedFields("id");
}

从纯粹的安全角度来看,白名单比黑名单更受欢迎,但它可能有助于减轻一些负担。

于 2013-04-16T13:15:48.313 回答
2

setAllowedFields() 在 web 层直接使用实体对象时非常方便。或者,可以使用专用数据传输对象 (DTO),在服务层中从中构造实体对象。不仅可以重用工厂,还可以在 Web 上下文之外使用,例如用于异步消息。此外,DTO 继承不必遵循实体继承,因此您可以根据用例的需要自由设计 DTO 层次结构。

于 2013-03-26T14:15:25.687 回答
0

来自http://static.springsource.org/spring-webflow/docs/2.0.x/reference/htmlsingle/spring-webflow-reference.html#view-model

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。

每个绑定还可以应用必要的检查,如果用户提供的值在表单回发时为空,则会生成验证错误:

<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>

在上面的示例中,所有绑定都是必需的。如果绑定了一个或多个空白输入值,则会生成验证错误,并且视图将重新呈现这些错误。

于 2013-06-26T17:45:42.877 回答
0

在大多数表单输入值应转换为 null(如果为空)的情况下使用带有 DTO(例如公司数据)的活页夹的解决方案,但需要添加一些异常(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));
}
于 2020-05-08T22:09:38.953 回答