问题:
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 个链接。”)
太多项目的结果(> 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/