Spring的数据绑定器autoGrowCollectionLimit无法正常工作

时间:2014-02-22 23:47:35

标签: java spring spring-mvc

  • 问题:

    Spring的数据绑定器允许您设置自动创建的List<>的最大大小(),例如到3项。通过修改发送到服务器的HTTP内容,可以轻松绕过此限制并使Spring创建3000多个项目的列表。

    换句话说:在测试我的webapp时,我能够通过创建恶意HTTP请求来强制Spring的数据绑定器创建List&lt;&gt;由4000件物品组成,虽然我已将限量设定为3件。这可能很容易导致任何应用服务器上的内存不足。

  • 问题:

    我是否遗漏了一些明显如何阻止Spring执行此操作的内容,或者更确切地说,这是一个应该向Spring的错误跟踪器报告的错误?

  • 使用的版本:

    弹簧工具套件-3.3.0.RELEASE,
    d:\平方米\回购\有机\ springframework的\弹簧的web \ 3.2.4.RELEASE \弹簧网络3.2.4.RELEASE.jar

  • 说明

    我需要将多个html <input />元素绑定到单个List<String>对象,例如:

    <input type="text" name="phoneNumber[0]" />
    ...
    <input type="text" name="phoneNumber[n]" />
    

    Spring默认使用org.springframework.beans.propertyeditors.CustomCollectionEditor执行此类转换。以下是一个简单的代码段,介绍了上述问题。

  • 代码:

    • 支持bean:

    public class ContactDataEntity {
        private List<String> phoneNumber;
        // getters and setters
    }
    
    • Binder in controller:

    @RequestMapping(value = VIEW_PAGE_1, method = RequestMethod.POST)
    public String xxx(HttpServletRequest request, Model model) {
    
        // set and bind
        ContactDataEntity contactData = new ContactDataEntity();
        ServletRequestDataBinder binder = new ServletRequestDataBinder(contactData);
        binder.setAutoGrowCollectionLimit(3); // set limit to 3 items
        binder.bind(request);
    
        // test binding results
        List<String> numbers = contactData.getPhoneNumber();
        if (numbers != null) {
            System.out.print("numbers SIZE: " + numbers.size() + ", DATA: ");
            for (String s : numbers) System.out.print(s + ", ");
            System.out.print("\n");
        }
    
        // validate and return view name...
    
    }
    
  • 正确数据的结果(&lt; = 3项,一切正常,我使用Firefox的Live HTTP Headers):

    (对不起图片的链接,但“你需要至少10个声望来发布图片。”和“你需要至少10个声望才能发布2个以上的链接。”)

    http://i.stack.imgur.com/AEjsA.jpg

  • 过多项目的结果(&gt; 3项,一切正常,500内部服务器错误发生):

    i.stack.imgur.com/MfWYy.jpg

  • 简单的伎俩(&gt; 3项,没有错误报告,抱歉我的拼写错误'覆盖'):

    i.stack.imgur.com/FNlXE.jpg

  • 让我们利用上述内容:

    i.stack.imgur.com/XPIhc.jpg

所以,我的问题再次提出:我是否遗漏了一些明显的事情,如何阻止Spring这样做,或者更确切地说,这是一个应该报告给Spring的bug追踪器的错误?

//编辑:
我把它报告为一个错误:https://jira.springsource.org/browse/SPR-11472

1 个答案:

答案 0 :(得分:2)

好的,在Spring 3.2.9和4.0.3的官方修复发布之前,我已经覆盖了Spring的默认CustomCollectionEditor来暂时修复这个bug。

唯一的缺点是你不能在你的HTML代码/ HTTP请求中使用它:

&phoneNumber=0
&phoneNumber=1
&phoneNumber=2
&phoneNumber=3

但您需要明确地为每个参数编制索引:

&phoneNumber[0]=0
&phoneNumber[1]=1
&phoneNumber[2]=2
&phoneNumber[3]=3

现在简单地忽略了不带[]的多个参数,请参阅以下代码中的注释。

package xxx;

import java.util.List;

import org.springframework.beans.propertyeditors.CustomCollectionEditor;

/**
 * @see <a href="https://jira.springsource.org/browse/SPR-11472">https://jira.springsource.org/browse/SPR-11472</a>
 */
public class CustomListEditorSPR11472 extends CustomCollectionEditor {

    @SuppressWarnings("rawtypes")
    public CustomListEditorSPR11472(Class<List> collectionType) {
        super(collectionType);
    }

    @Override
    public void setValue(Object value) {
        /*
         * Force Spring to ignore all HTTP request **MULTIPLE** parameters without "[]" on the end so that
         * binder.setAutoGrowCollectionLimit() could work correctly. Example:
         *
         * phoneNumber[2]=2
         * Above request is OK, a List containing: 'null, null, 2' is created.
         *
         * phoneNumber=2
         * Above request is OK, **SINGLE** parameter without "[]", a List containing: '2' is created
         *
         * phoneNumber[0]=0&phoneNumber=1&phoneNumber=2
         * **MULTIPLE** parameters without "[]" are ignored, a List containing: '0' is created.
         */

        if ((value != null && value.getClass().isArray()) == false) {
            super.setValue(value);
        }
    }

}

当然,您还需要在活页夹中注册CustomEditor:

binder.registerCustomEditor(List.class, new CustomListEditorSPR11472(List.class));

或单个属性的更细粒度版本:

binder.registerCustomEditor(List.class, "phoneNumber", new CustomListEditorSPR11472(List.class));