Spring Boot1.5升级2.7.1后415错误跳转登录页无法返回JSON
问题背景
Spring Boot从1.5.21升级至2.7.1、Java从8升级至17后,控制器异常返回逻辑异常:
- 接口
/test/{name}/submitinfo通过consumes = MediaType.APPLICATION_JSON_VALUE配置仅接收application/json类型请求,非JSON格式请求本应返回415 Unsupported Media Type的标准JSON错误,实际返回HTML格式登录页 - 注释
WebSecurityConfig类中configure(final HttpSecurity http)方法后功能恢复正常,该逻辑在Spring Boot 1.5.21版本中可正常运行
相关代码
控制器代码
@RestController @RequestMapping(path = "/test") public class SubmissionController { @PostMapping(value = "/{name}/submitinfo", consumes = MediaType.APPLICATION_JSON_VALUE) @ResponseBody public ResponseEntity submit(@PathVariable("name") final String name, @RequestBody final String data) { // 业务逻辑省略 } }
安全配置代码
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled = true, proxyTargetClass = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(final HttpSecurity http) throws Exception { http .csrf().disable(); http .authorizeRequests() .antMatchers("/Demo/**").permitAll() .anyRequest().fullyAuthenticated() .and() .formLogin() .loginPage("/Demo/login") .usernameParameter(USERNAME) .passwordParameter(PASSWORD) .successHandler(authSuccessHandler) .failureHandler(authFailureHandler) .permitAll() .and() .logout() .logoutUrl("/Demo/logout") .invalidateHttpSession(true) .deleteCookies(JSESSIONID) .logoutSuccessHandler(logoutSuccessHandler) .and() .exceptionHandling() .accessDeniedPage(ACCESS_DENIED); } @Override public void configure(final WebSecurity web) throws Exception { web.ignoring().antMatchers("/test/**"); } }
关键异常日志
2022-07-06 05:53:40 36119 [http-nio-8080-exec-5] DEBUG o.s.w.s.DispatcherServlet correlationId= sessionid=E0DC60ECB2E5D0A87E6E8A25131279DD - Completed 415 UNSUPPORTED_MEDIA_TYPE 2022-07-06 05:53:40 36121 [http-nio-8080-exec-5] DEBUG o.s.s.web.FilterChainProxy correlationId= sessionid=E0DC60ECB2E5D0A87E6E8A25131279DD - Securing POST /error 2022-07-06 05:53:40 36122 [http-nio-8080-exec-5] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter correlationId= sessionid=E0DC60ECB2E5D0A87E6E8A25131279DD - Set SecurityContextHolder to empty SecurityContext 2022-07-06 05:53:40 36123 [http-nio-8080-exec-5] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter correlationId= sessionid=E0DC60ECB2E5D0A87E6E8A25131279DD - Set SecurityContextHolder to anonymous SecurityContext 2022-07-06 05:53:40 36127 [http-nio-8080-exec-5] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor correlationId= sessionid=E0DC60ECB2E5D0A87E6E8A25131279DD - Failed to authorize filter invocation [POST /error] with attributes [fullyAuthenticated] 2022-07-06 05:53:40 36129 [http-nio-8080-exec-5] DEBUG o.s.s.w.s.HttpSessionRequestCache correlationId= sessionid=E0DC60ECB2E5D0A87E6E8A25131279DD - Saved request http://localhost:8080/error to session 2022-07-06 05:53:40 36129 [http-nio-8080-exec-5] DEBUG o.s.s.w.DefaultRedirectStrategy correlationId= sessionid=E0DC60ECB2E5D0A87E6E8A25131279DD - Redirecting to http://localhost:8080/Demo/login
预期返回格式
{ "timestamp": "2022-07-06T06:08:30.894+00:00", "status": 415, "error": "Unsupported Media Type", "path": "/test/ghsahgs/submitinfo" }
问题根因
从日志可直接定位问题:
- 控制器本身已经正常抛出415异常,Servlet容器会将请求转发到Spring Boot默认的
/error端点统一处理错误响应 - 现有配置仅在
WebSecurity忽略规则中放行了/test/**路径,未放行/error路径。Spring Security拦截了转发到/error的请求,判定当前为匿名未认证状态后,直接重定向到登录页,因此最终返回HTML登录内容而非JSON错误 - Spring Boot 1.x版本对错误端点的默认安全放行逻辑与2.x版本存在差异,升级后该默认行为变更导致问题暴露。
解决方案
在configure(HttpSecurity http)方法的授权规则中补充/error路径的匿名访问权限即可,修改后的授权配置如下:
http .csrf().disable(); http .authorizeRequests() .antMatchers("/Demo/**", "/error").permitAll() // 新增/error路径放行 .anyRequest().fullyAuthenticated() .and() // 其余formLogin、logout、exceptionHandling配置保持原有逻辑不变
注意:不要把
/error路径加到web.ignoring()规则中,该配置会让请求完全绕过安全过滤器链,可能导致错误场景下安全上下文丢失,使用permitAll()放行即可满足匿名访问错误端点的需求。
修改后重启服务,非JSON请求即可返回预期的标准JSON格式415错误响应。
内容的提问来源于stack exchange,提问作者sinsanarya
相关产品推荐
相关产品推荐

