使用嵌套的允许字段播放框架 2 (Java) 表单数据绑定

考虑以下模型:

public class Contact {

  @Required
  public String name;

  @Valid
  public List<Information> informations;

  }

  public static class Information {

    public String securedField;

    @Required
    public String email;

    @Valid
    public List<Phone> phones;

    public static class Phone {

      @Required
      @Pattern(value = "[0-9.+]+", message = "A valid phone number is required")
      public String number;
    }

  }

}

我不希望 InformationsecureField 受到 批量分配漏洞.所以我决定为 Contact Form 设置 allowedFields 数组.

I don't want Information securedField to be affected by mass assignment vulnerability. So i decided to set array of allowedFields for Contact Form.

据我所知,播放表单是基于Spring DataBinder的,所以可以处理集合字段吗?我不想这样写:

As i know, play forms are based on Spring DataBinder, so is it possible to handle collection fields? I don't want to write smth like:

  • 姓名
  • 信息[0].email
  • 信息[0].phones*
  • 信息[1].email
  • 信息[1].phones*

以下不起作用:

  • 姓名
  • 信息.电子邮件
  • 信息.电话*

在这种情况下我应该扩展现有的 Spring DataBinderForm 类并覆盖 bind 方法吗?

Should i extend existing Spring DataBinder and Form classes and override bind method in this case?

推荐答案

这是一个可以说是更简单的解决方案.如果 POST 数据包含任何 informations[%d].securedField 值,如何定义将触发验证失败的额外约束?

Here's an arguably simpler solution. How about defining an extra constraint that will trigger a validation failure if the POST data contains any informations[%d].securedField values?

import javax.validation.constraints.Null;

public static class Information {

    @Null
    public String securedField;

    ...

}

我认为这样您可以调用默认的 bindFromRequest 方法,而不是接受表单字段名称白名单的方法,并且仍然可以防止批量分配攻击.

I think that this way you can call the default bindFromRequest method instead of the one that accepts a whitelist of form field names, and still be protected against a mass assignment attack.

不可否认,这种方法的一个缺点是,如果发生协同的批量分配攻击,它最终会泄露您的内部字段的名称.但是,如果它们的名称相当平淡无奇,例如 securedField(无意冒犯!),我不确定攻击者如何利用这些信息.

One shortcoming with this approach admittedly is that it would ultimately leak the names of your internal fields in the event of a concerted mass assignment attack. However if they had fairly bland, meaningless names such as securedField (no offence intended!), I'm not sure how this information could be exploited by an attacker.

如果您想允许根据当前用户类型分配给字段,也许 bean 验证组会有所帮助:

If you want to allow assignment to the field based on the current user type, maybe bean validation groups could help:

import javax.validation.constraints.Null;

public class Contact {

    public interface Administrator {}

    public interface User {}

    ...

    public class Information {

        @Null(groups = User.class)
        public String securedField;

        ...

    }

}

控制器代码

...
final Form<Contact> contactForm;
if (currentUser.isAdministrator()) {
    contactForm = form(Contact.class, Administrator.class).bindFromRequest();
} else {
    contactForm = form(Contact.class, User.class).bindFromRequest();
}
...

相关文章