【问题标题】:Could not handle FileTooLargeException in @RestControllerAdvice after enabling jwt in spring security在 Spring Security 中启用 jwt 后无法处理 @RestControllerAdvice 中的 FileTooLargeException
【发布时间】:2021-11-01 23:34:42
【问题描述】:

我有带有 undertow 容器的 Spring Boot 应用程序。有一个 rest 控制器接受如下所示的文件:

  @ResponseStatus(HttpStatus.CREATED)
  @PostMapping(value = {"/v2/upload-csv"},
               produces = {MediaType.APPLICATION_JSON_VALUE},
               consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
  public List<ChordInfo> uploadFile(@RequestPart @NotNull(message = "File is not provided!") MultipartFile file) {
    return chordService.handleFile(file);
  }

使用MaxUploadSizeExceededException 异常处理程序

  @ExceptionHandler
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  public ErrorResponse handleFileSizeException(MaxUploadSizeExceededException exception) {
    return ErrorResponse.singleError(new Error(
            ErrorCode.UPLOAD_SIZE_EXCEEDED,
            exception.getMessage(),
            new UploadSizeExceededMeta(exception.getMaxUploadSize())
        )
    );
  }

及基本认证配置:

@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
        .cors().and().csrf().disable()
        .authorizeRequests()
        .antMatchers("/**").permitAll()
        .and()
        .httpBasic();
  }
}

在我用 JWT 将基本身份验证替换为 oauth2 资源服务器之前,它一直运行良好。现在配置是这样的

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
        .httpBasic().disable()
        .csrf().disable()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .authorizeRequests()
        .anyRequest().permitAll()
        .and()
        .oauth2ResourceServer()
        .jwt();
  }

如果我尝试上传超出限制的文件,应用程序会返回 500 并带有默认 spring 的异常:

{
  "timestamp": "2021-09-03T16:08:13.341+00:00",
  "status": 500,
  "error": "Internal Server Error",
  "message": "",
  "path": "/v2/upload-csv"
}

我该如何解决? 我发现将容器替换为 Tomcat 可以解决问题,但我想继续跟进。

UPD1 这是启用 jwt 的堆栈跟踪

ERROR io.undertow.request - UT005023: Exception handling request to /v2/upload-csv
java.lang.IllegalStateException: io.undertow.server.handlers.form.MultiPartParserDefinition$FileTooLargeException: UT000054: The maximum size 1048576 for an individual file in a multipart request was exceeded
    at io.undertow.servlet.spec.HttpServletRequestImpl.parseFormData(HttpServletRequestImpl.java:855) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.spec.HttpServletRequestImpl.getParameterValues(HttpServletRequestImpl.java:778) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at javax.servlet.ServletRequestWrapper.getParameterValues(ServletRequestWrapper.java:174) ~[jakarta.servlet-api-4.0.4.jar:4.0.4]
    at javax.servlet.ServletRequestWrapper.getParameterValues(ServletRequestWrapper.java:174) ~[jakarta.servlet-api-4.0.4.jar:4.0.4]
    at org.springframework.security.web.firewall.StrictHttpFirewall$StrictFirewalledRequest.getParameterValues(StrictHttpFirewall.java:721) ~[spring-security-web-5.4.2.jar:5.4.2]
    at javax.servlet.ServletRequestWrapper.getParameterValues(ServletRequestWrapper.java:174) ~[jakarta.servlet-api-4.0.4.jar:4.0.4]
    at org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver.resolveFromRequestParameters(DefaultBearerTokenResolver.java:116) ~[spring-security-oauth2-resource-server-5.4.2.jar:5.4.2]
    at org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver.resolve(DefaultBearerTokenResolver.java:52) ~[spring-security-oauth2-resource-server-5.4.2.jar:5.4.2]
    at org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter.doFilterInternal(BearerTokenAuthenticationFilter.java:106) ~[spring-security-oauth2-resource-server-5.4.2.jar:5.4.2]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) ~[spring-web-5.3.3.jar:5.3.3]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) ~[spring-web-5.3.3.jar:5.3.3]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.3.jar:5.3.3]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.3.jar:5.3.3]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at org.springframework.cloud.sleuth.instrument.web.servlet.TracingFilter.doFilter(TracingFilter.java:89) ~[spring-cloud-sleuth-instrumentation-3.0.1.jar:3.0.1]
    at org.springframework.cloud.sleuth.autoconfig.instrument.web.LazyTracingFilter.doFilter(TraceWebServletConfiguration.java:121) ~[spring-cloud-sleuth-autoconfigure-3.0.1.jar:3.0.1]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at org.zalando.logbook.servlet.LogbookFilter.doFilter(LogbookFilter.java:71) ~[logbook-servlet-2.4.2.jar:na]
    at org.zalando.logbook.servlet.SecureLogbookFilter.doFilter(SecureLogbookFilter.java:32) ~[logbook-servlet-2.4.2.jar:na]
    at org.zalando.logbook.servlet.HttpFilter.doFilter(HttpFilter.java:31) ~[logbook-servlet-2.4.2.jar:na]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93) ~[spring-boot-actuator-2.4.2.jar:2.4.2]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.3.jar:5.3.3]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:117) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.SendErrorPageHandler.handleRequest(SendErrorPageHandler.java:52) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:78) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:99) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:387) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:841) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]
    at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1558) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1449) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]
    at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]
Caused by: io.undertow.server.handlers.form.MultiPartParserDefinition$FileTooLargeException: UT000054: The maximum size 1048576 for an individual file in a multipart request was exceeded
    at io.undertow.server.handlers.form.MultiPartParserDefinition$MultiPartUploadHandler.data(MultiPartParserDefinition.java:272) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.util.MultipartParser$IdentityEncoding.handle(MultipartParser.java:365) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.util.MultipartParser$ParseState.entity(MultipartParser.java:343) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.util.MultipartParser$ParseState.parse(MultipartParser.java:131) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.server.handlers.form.MultiPartParserDefinition$MultiPartUploadHandler.parseBlocking(MultiPartParserDefinition.java:232) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.spec.HttpServletRequestImpl.parseFormData(HttpServletRequestImpl.java:853) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    ... 86 common frames omitted

【问题讨论】:

  • 如果不知道异常的实际原因(堆栈跟踪可能在您的应用程序中),这将无法回答。
  • @M.Deinum 抱歉回复太长,我在 UPD1 中附加了堆栈跟踪
  • 堆栈跟踪很清楚地表明您正在上传大于配置(或默认)限制的文件。更改上传限制。
  • 请检查主题和问题描述。问题与限制配置无关,而是这种类型的异常处理

标签: java spring spring-security-oauth2 undertow


【解决方案1】:

这是默认的最大多部分文件大小(1048576 字节 = 1MB)。当然你可以改变这个限制。

spring.servlet.multipart.max-file-size = 10MB
spring.servlet.multipart.max-request-size = 10MB

【讨论】:

  • 请检查主题和问题描述。该问题与限制配置无关,而是与这种类型的异常处理有关。我尝试明确设置限制,但问题没有解决
  • 好吧,我的错。在我看到的堆栈跟踪中,FileTooLargeException 不是MaxUploadSizeExceededException。你检查过吗?
猜你喜欢
  • 2019-06-28
  • 2022-12-11
  • 2022-11-11
  • 2020-08-16
  • 2021-10-31
  • 2017-10-03
  • 2016-12-30
  • 2013-03-30
  • 1970-01-01
相关资源
最近更新 更多