gpt4 book ai didi

spring - 如何使用 Spring Security 很好地处理文件上传 MaxUploadSizeExceededException

转载 作者:IT老高 更新时间:2023-10-28 13:51:36 25 4
gpt4 key购买 nike

我正在使用 Spring Web 4.0.5、Spring Security 3.2.4、Commons FileUpload 1.3.1、Tomcat 7,我得到了一个丑陋的 MaxUploadSizeExceededException当我的上传大小超出限制时,会导致“500 内部服务器错误”。我用一个很好的通用弹出窗口来处理它,但我宁愿让我的 Controller 通过正确的解释消息返回原始表单来处理它。

我已经多次看到类似的问题,其中一些解决方案在不使用 Spring Security 时可能会起作用;我试过的没有一个对我有用。

问题可能是在使用 Spring Security 时,CommonsMultipartResolver不是作为“multipartResolver”bean 添加的,而是作为“filterMultipartResolver”添加的:

@Bean(name="filterMultipartResolver")
CommonsMultipartResolver filterMultipartResolver() {
CommonsMultipartResolver filterMultipartResolver = new CommonsMultipartResolver();
filterMultipartResolver.setMaxUploadSize(MAXSIZE);
return filterMultipartResolver;
}

如果我设置 filterMultipartResolver.setResolveLazily(true);没有区别。

如果我将 CommonsMultipartResolver 子类化用我自己的并覆盖 parseRequest()带有陷阱 MaxUploadSizeExceededException 的方法并返回一个空的 MultipartParsingResult ,我收到“403 Forbidden”错误:

public class ExtendedCommonsMultipartResolver extends CommonsMultipartResolver {
protected MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException {
String encoding = determineEncoding(request);
try {
return super.parseRequest(request);
} catch (MaxUploadSizeExceededException e) {
return parseFileItems(Collections.<FileItem> emptyList(), encoding);
}
}
}

最后,实现某种本地或全局的ExceptionHandler 毫无意义。因为它永远不会被调用。

如果我没有找到更好的解决方案,我将删除上传大小限制并在 Controller 中自行处理,缺点是让用户等到上传完成后才能看到有关文件的错误消息尺寸。我什至可能会忽略所有这些,因为在这种情况下,作为图像,我可以将其调整为适当的值。

不过,我还是想看看这个问题的解决方案。

谢谢

编辑:

我按要求添加堆栈跟踪。这是生成 500 的情况。

May 30, 2014 12:47:17 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/site] threw exception
org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size of 1000000 bytes exceeded; nested exception is org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (3403852) exceeds the configured maximum (1000000)
at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:162)
at org.springframework.web.multipart.commons.CommonsMultipartResolver.resolveMultipart(CommonsMultipartResolver.java:142)
at org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:110)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:409)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1044)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (3403852) exceeds the configured maximum (1000000)
at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:965)
at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:310)
at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:334)
at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:115)
at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:158)
... 19 more

最佳答案

您可以通过添加额外的过滤器来捕获异常并重定向到错误页面来处理 MaxUploadSizeExceededException。例如,您可以创建一个 MultipartExceptionHandler 过滤器,如下所示:

public class MultipartExceptionHandler extends OncePerRequestFilter {

@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
filterChain.doFilter(request, response);
} catch (MaxUploadSizeExceededException e) {
handle(request, response, e);
} catch (ServletException e) {
if(e.getRootCause() instanceof MaxUploadSizeExceededException) {
handle(request, response, (MaxUploadSizeExceededException) e.getRootCause());
} else {
throw e;
}
}
}

private void handle(HttpServletRequest request,
HttpServletResponse response, MaxUploadSizeExceededException e) throws ServletException, IOException {

String redirect = UrlUtils.buildFullRequestUrl(request) + "?error";
response.sendRedirect(redirect);
}

}

注意:此重定向对您的表单和上传进行假设。您可能需要修改重定向到的位置。具体来说,如果您遵循表单在 GET 时的模式并在 POST 时处理它,这将起作用。

然后您可以确保在 MultipartFilter 之前添加此过滤器。例如,如果您使用的是 web.xml,您会看到如下内容:

<filter>
<filter-name>meh</filter-name>
<filter-class>org.example.web.MultipartExceptionHandler</filter-class>
</filter>
<filter>
<description>
Allows the application to accept multipart file data.
</description>
<display-name>springMultipartFilter</display-name>
<filter-name>springMultipartFilter</filter-name>
<filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
<!--init-param>
<param-name>multipartResolverBeanName</param-name>
<param-value>multipartResolver</param-value>
</init-param-->
</filter>
<filter>
<description>
Secures access to web resources using the Spring Security framework.
</description>
<display-name>springSecurityFilterChain</display-name>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
<filter-name>meh</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>springMultipartFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>ERROR</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>

在您的表单中,您可以通过检查是否存在 HTTP 参数错误来检测是否发生了错误。例如,在 JSP 中,您可能会执行以下操作:

<c:if test="${param.error != null}">
<p>Failed to upload...too big</p>
</c:if>

PS:我创建了 SEC-2614更新文档以讨论错误处理

关于spring - 如何使用 Spring Security 很好地处理文件上传 MaxUploadSizeExceededException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23856254/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com