Struts2 [Error]:multipart.JakartaMultiPartRequest:68 - Request exceeded size limit!
struts2 版本:struts2.3.20
- 错误信息
multipart.JakartaMultiPartRequest:68 - Request exceeded size limit!
org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (1418624662) exceeds the configured maximum (20971520)
-
问题剖析
-
从错误信息,可以很清楚的看出:问题的根源是上传文件过大。
-
背景:使用 Struts2 上传文件
-
下面为对应的部分
jsp
代码<form action="..."/>" method="post" enctype="multipart/form-data"> <table> <td> <input type="file" name="upload"/> </td> <td> <input type="submit" value="提交"> </td> </table> </form>
-
下面为部分
struts.xml
配置<action name="linkMan_*" class="linkManAction" method="{1}"> <result name="addLinkMan" type="dispatcher">/index.jsp</result> <result name="addSuccess" type="dispatcher">/index.jsp</result> <result name="input" type="redirect">/index.jsp</result> </action>
-
下面是对应的
LinkManAction.java
类中上传文件的配置//上传文件 private File upload; //上传文件名 private String uploadFileName; //省略了 set get 方法 ... //保存代码 File file = new File("E:\\CRM\\" + uploadFileName); FileUtils.copyFile(upload, file);
-
-
剖析
-
struts2 中默认可上传最大为 2MB 的文件。当然,这可满足我们大部分需要,而就算有更大的文件需能上传,我们也可以通过以下全局配置来扩展。
<!-- 配置上传文件允许的最大大小 --> <constant name="struts.multipart.maxSize" value="20971520"/>
-
可是,再大也有尽头。如果用户不小心上传了一个很大的文件,我们该怎么办?
- 不得不说
struts2
很棒!若遇到上传的文件比设置的最大可接受值大时,它会抛出最上面的异常。并且,正常的话 还会返回 input 以方便我们可以跳转到错误页面友好地提醒用户。请注意我说的是正常的话,如果一切都是正常的我就不会写这博客了。。。 - 从上面的
struts.xml
中可以很清楚的看到我已经设置了input
对应的result
。然而,我上传一个大文件进行测试的时,最后浏览器每次都显示连接中断。。。这不科学啊!我的友好提示呢!
- 不得不说
-
-
调试
- 1)是不是地址写错
- 于是我上传了一个小文件,结果很正常。我在服务器里面找到了上传的文件。
- 我便排除了这种可能。
- 2)难道并不返回 input
-
于是,我尝试去掉
struts2.xml
中的关于input
的result
配置,然后跑一下。当我测试上传一个大文件时,除了最上面的异常,还抛出了:No result defined for action action.LinkManAction and result input - action - file:/D:/project/CRM/out/artifacts/SSH_war_exploded/WEB-INF/classes/struts.xml:40:69
-
这分明是提示我没写
input
对应的result
。可是,我配置了后为嘛又不跳转呢(上面我分明写上了)。我不死心,又把它加上了,可结果一样:浏览器依然以连接中断结束。 -
这 TM 到底怎么了!!!
-
- 3)于是我开始
Google
,巨大发现。。。- Struts2 高危漏洞 (CVE-2017-5638) 点我
- 不会吧,我就随便练习一下
struts2
,居然让我碰到高危漏洞了。 - 放弃了,不弄了,估计就是那漏洞的问题了,现已累成狗~~~
- 4)这心态不对!问题总是要解决的!唉,肯定不是漏洞的问题。理性分析一波(偷笑,小胖子)
-
开启调试模式!给默认的拦截器
StrutsPrepareAndExecuteFilter
打上断点,我看看它究竟是在哪里抛出的异常! -
我发现,这货居然没等到
FileUploadInterceptor
就结束了。FileUploadInterceptor
可是正宗的处理文件上传的拦截器啊! -
没想到,在进入
FileUploadInterceptor
之前,还有FileUploadBase
验身,它发现文件过大时就会抛出上述异常。且按照正常的说,还会返回input
。 -
新的解决方案:既然你能抛出异常,我如下设置不就行了嘛
<global-results> <result name="error">/index.jsp</result> </global-results> <global-exception-mappings> <exception-mapping exception="org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException" result="error"/> </global-exception-mappings>
-
结果还是那样,不起作用啊!MMP!到底哪里错了!是谁吞了 input ?
-
-
- 新思路
-
我惹不起,还躲不起吗?
-
我把你配置为最大值 (struts.multipart.maxSize 要求 value 是一个 int)
<!-- 配置上传文件允许的最大大小 --> <constant name="struts.multipart.maxSize" value="2147483647"/>
-
这样
FileUploadBase
就没有理由拦下来了。于是,可以顺畅的进入FileUploadInterceptor
-
因为
FileUploadInterceptor
是正宗的文件上传拦截器,所有也可以设置允许的上传文件大小<interceptor-ref name="fileUpload"> <param name="maximumSize">2097152</param> </interceptor-ref> <interceptor-ref name="defaultStack" />
-
果然成功了!那个 input 居然返回来了,于是
input
对应的result
起来作用!(爽~~~然而,让我绕了这么大弯子!) -
这样,在用户不小心上传超大文件时,我们就可以进行友好提示了!
- 1)是不是地址写错
-
-
最终还是有疑问
- 那个 input 到底去哪里了?为什么不写
input
对应的result
时会有警告,而写上有不起作用了?到底哪里错了?真的与struts2
漏洞有关(几率很小),还是一个新struts2
的 bug ? - 虽然有了解决方案,但是还有好多疑问,以后读源码时一定要解决!!!
- 那个 input 到底去哪里了?为什么不写