【问题标题】:Spring's data binder autoGrowCollectionLimit doesn't work correctlySpring 的数据绑定器 autoGrowCollectionLimit 无法正常工作
【发布时间】:2014-02-22 23:47:35
【问题描述】:
  • 问题:

    Spring 的数据绑定器允许您设置自动创建的List<> 的最大 size(),例如到 3 项。绕过这个限制很容易,只需修改发送到服务器的 HTTP 内容,Spring 就会创建一个包含 3000 多个项目的列表。

    换句话说:在测试我的 web 应用程序时,我能够通过创建恶意 HTTP 请求来强制 Spring 的数据绑定器创建一个包含 4000 个项目的 List,尽管我将限制设置为 3 个项目.这可能很容易导致任何应用服务器上的内存不足异常。

  • 问题:

    我是否遗漏了一些明显的东西,如何防止 Spring 这样做,或者更确切地说,这是一个应该报告给 Spring 的错误跟踪器的错误?

  • 使用的版本:

    spring-tool-suite-3.3.0.RELEASE,
    D:\m2\repo\org\springframework\spring-web\3.2.4.RELEASE\spring-web-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 执行此类转换。下面是一个简单的代码 sn-p 呈现上述问题。

  • 代码:

    • 支持 bean:

    public class ContactDataEntity {
        private List<String> phoneNumber;
        // getters and setters
    }
    
    • 控制器中的绑定器:

    @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...
    
    }
    
  • 正确数据的结果(

    (抱歉,提供了图片链接,但“您需要至少 10 个声誉才能发布图片。”和“您需要至少 10 个声誉才能发布超过 2 个链接。”)

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

  • 结果太多项目(> 3 个项目,一切正常,发生 500 内部服务器错误):

    i.stack.imgur.com/MfWYy.jpg

  • 简单的技巧(> 3 个项目,没有报告错误,抱歉我在“覆盖”中的错字):

    i.stack.imgur.com/FNlXE.jpg

  • 让我们利用上述内容:

    i.stack.imgur.com/XPIhc.jpg

所以,我的问题又来了:我是否遗漏了一些明显的东西,如何防止 Spring 这样做,或者更确切地说,这是一个应该报告给 Spring 的错误跟踪器的错误?

// 编辑:
我将其报告为错误:https://jira.springsource.org/browse/SPR-11472

【问题讨论】:

    标签: java spring spring-mvc


    【解决方案1】:

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

    唯一的缺点是你不能在你的 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));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-28
      • 2013-04-03
      • 1970-01-01
      • 2017-05-22
      • 1970-01-01
      • 1970-01-01
      • 2015-11-18
      • 1970-01-01
      相关资源
      最近更新 更多