You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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"
}
问题根因

从日志可直接定位问题:

  1. 控制器本身已经正常抛出415异常,Servlet容器会将请求转发到Spring Boot默认的/error端点统一处理错误响应
  2. 现有配置仅在WebSecurity忽略规则中放行了/test/**路径,未放行/error路径。Spring Security拦截了转发到/error的请求,判定当前为匿名未认证状态后,直接重定向到登录页,因此最终返回HTML登录内容而非JSON错误
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 13:24:22