java - Spring 的数据绑定(bind)器 autoGrowCollectionLimit 不能正常工作

标签 java spring spring-mvc

  • 问题:

    Spring 的数据绑定(bind)器允许您设置自动创建的最大 size() List<>例如到 3 项。绕过此限制并使 Spring 只需修改发送到服务器的 HTTP 内容即可创建包含 3000 多个项目的列表非常容易。

    换句话说:在测试我的 webapp 时,我能够通过创建恶意 HTTP 请求来强制 Spring 的数据绑定(bind)器创建一个包含 4000 个项目的列表<>,尽管我已将限制设置为 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

  • 描述:

    我需要绑定(bind)多个 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
    }
    
    • Controller 中的绑定(bind)器:

    @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...
    
    }
    
  • 正确数据的结果(<= 3 项,一切正常,我使用 Firefox 的实时 HTTP header ):

    (抱歉图片链接,但是“您至少需要 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

最佳答案

好的,在 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);
        }
    }

}

当然,你还需要在你的 Binder 中注册你的CustomEditor:

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

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

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

关于java - Spring 的数据绑定(bind)器 autoGrowCollectionLimit 不能正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21962228/

相关文章:

java - 配置bean未初始化

java - 不能 Mockbean HttpServletResponse

spring-mvc - 如何在 Spring MVC 中填充下拉列表

java - 使用 spring mvc 和 jackson 允许带或不带根节点的 json 的正确方法

java - 在 Spring 中如何审计端点通信?

java - 我的 Java 斐波那契数列有误吗?

java - 在Processing/Java的链接列表中找到5个最大的值

java - Android/Java 改造 : Class cannot be converted to Callback

java - 在 Spring 中的存储过程中传递参数

spring - 无法解决Grails自定义验证程序问题