Spring Boot POST 请求返回 http 状态 405“Method Not Allowed”而不是 HTTP 状态 404

时间:2021-07-09 14:27:59

标签: java spring http http-status-code-500 http-status-code-405

当向应用程序中不存在的端点发送 POST 请求时,服务器返回 405 而不是 404。对于具有现有端点的请求也会发生类似的问题,只要一切正常,状态代码就会返回 200,但是当发生内部服务器错误(例如找不到用户)时,http 响应变为 405(而不是 500)。使用 GET 请求,一切正常。

奇怪的是,如果我打开调试器,按照抛出错误的过程,它正在处理一个 500 错误。但显然最终某处出了问题,我得到了 405 返回。

我的网络安全配置:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

  @Autowired
  private UserDetailsService jwtUserDetailsService;

  @Autowired
  private JwtRequestFilter jwtRequestFilter;

  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    // configure AuthenticationManager so that it knows from where to load
    // user for matching credentials
    // Use BCryptPasswordEncoder
    auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
  }

  @Bean
  public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }

  @Bean
  @Override
  public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
  }

  @Value("${allowedOrigin}")
  private String origin = "http://localhost:4200";

  @Override
  protected void configure(HttpSecurity httpSecurity) throws Exception {
    //You can enforce the use of HTTPS when your app is running on Heroku by adding
    // the following configuration to your Spring Boot app.
    httpSecurity.requiresChannel()
      .requestMatchers(r - > r.getHeader("X-Forwarded-Proto") != null)
      .requiresSecure();


    httpSecurity
      .cors()
      .and().csrf()
      .disable()
      // dont authenticate this particular request
      .authorizeRequests()
      .antMatchers("/api/authenticate")
      .permitAll()
      // all other requests for /api need to be authenticated
      .antMatchers("/api/**", "/admin/**")
      .authenticated()
      .and()
      .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    // Add a filter to validate the tokens with every request
    httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);

  }

  @Bean
  CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList("*"));
    configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
    configuration.setAllowedHeaders(Arrays.asList("*"));
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
  }
}

更新:

我没有任何 ControllerAdivce,也没有编写全局异常处理程序。

405 响应中的“Allow”标头显示为“GET, HEAD”,即使 POST 请求实际进入 POST 端点也是如此。

2 个答案:

答案 0 :(得分:0)

根据您的 HttpSecurity 配置,您只允许 Post 请求,对于其他 HTTP 方法(如 GET、PUT....),您将获得 405(不允许的方法)。

 antMatchers(HttpMethod.POST).permitAll();

答案 1 :(得分:0)

事实证明,一个带有未实现的“/error”路径方法的 ErrorController 导致了问题。每当抛出异常或错误时,它都会解析为“/error”并被 ErrorController 接收,出于某种原因将其解析为 405。实现该方法后,HTTP 状态将正确返回。

@RestController
public class RoutingController implements ErrorController {

  private static final String PATH = "/error";

  @RequestMapping(value = PATH)
  public String handleError(HttpServletRequest request) {
    Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
    Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception");
    return String.format("<html><body><h2>Error Page</h2><div>Status code: <b>%s</b></div>" +
      "<div>Exception Message: <b>%s</b></div><body></html>",
      statusCode, exception == null ? "N/A" : exception.getMessage());
  }

  public String getErrorPath() {
    return PATH;
  }
}

相关问题