春季:不允许的方法返回错误代码403(禁止)而不是405

时间:2019-05-30 20:05:12

标签: spring rest spring-boot oauth-2.0 spring-profiles

我正在Spring中创建一个REST API,该API需要在Oauth2客户端凭证流中充当ResouceServer。我试图在开发和测试期间取消对客户端证书的需求,因此我创建了两个配置文件:“本地”和“云”。这是每个配置文件的安全性配置。

@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
@Profile("cloud")
public class CloudSecurityConfiguration extends ResourceServerConfigurerAdapter {

  @Autowired
  private MyEntryPoint myEntryPoint;

  @Override
  public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
    resources.resourceId("res-id");          
    resources.authenticationEntryPoint(myEntryPoint);
  }

  @Override
  public void configure(HttpSecurity http) throws Exception {
      http
              .authorizeRequests()
              .antMatchers("/").permitAll()
              .antMatchers("/.../**").fullyAuthenticated();
  }

}

-

@Component
@Profile("cloud")
public class MyEntryPoint implements AuthenticationEntryPoint {

  @Autowired
  private HandlerExceptionResolver handlerExceptionResolver;

  @Override
  public void commence(HttpServletRequest request, HttpServletResponse response,
                     AuthenticationException authException) throws IOException, ServletException {
      handlerExceptionResolver.resolveException(request, response, null, authException);
  }
}

本地

@Configuration
@EnableWebSecurity
@Profile("local")
@Order(Ordered.HIGHEST_PRECEDENCE)
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class LocalSecurityConfiguration extends WebSecurityConfigurerAdapter {
  @Override
  public void configure(HttpSecurity http) throws Exception {
      http.authorizeRequests().anyRequest().permitAll();
  }
}

({@EnableWebSecurity用于本地配置文件而不是@EnableResourceServer,因为它解决了一个奇怪的问题:如果标头中存在令牌(即使不需要),则本地配置文件中的每个端点总是返回错误响应Invalid access token

现在的问题是:API仅支持GET方法,我必须遵循严格的规范,即当将具有其他方法(如POST)的请求发送到服务器时,该方法应返回405错误代码。使用安全层,它可以与扩展@ControllerAdvice的{​​{1}}类一起正常工作,但是当我尝试通过切换到“本地”配置文件来删除安全层时,在测试中我收到了403-禁止错误,而不是405。

这是我的ResponseEntityExceptionHandler

ResponseEntityExceptionHandler

Ex(具有“本地”配置文件):

@ControllerAdvice public class MyErrorHandler extends ResponseEntityExceptionHandler { @ExceptionHandler @ResponseBody @ResponseStatus(HttpStatus.BAD_REQUEST) protected ErrorModel handleAllExceptions(ConstraintViolationException e, ServletWebRequest request) { return exceptionMapping(e, request, HttpStatus.BAD_REQUEST, TypeEnum.V); } @ExceptionHandler @ResponseBody @ResponseStatus(HttpStatus.UNAUTHORIZED) protected ErrorModel handleAllExceptions(AuthenticationException e, ServletWebRequest request) { return exceptionMapping(e, request, HttpStatus.UNAUTHORIZED, TypeEnum.S); } @ExceptionHandler @ResponseBody @ResponseStatus(HttpStatus.FORBIDDEN) protected ErrorModel handleAllExceptions(AccessDeniedException e, ServletWebRequest request) { return exceptionMapping(e, request, HttpStatus.FORBIDDEN, TypeEnum.S); } @ExceptionHandler @ResponseBody @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) protected ErrorModel handleAllExceptions(Exception e, ServletWebRequest request) { return exceptionMapping(e, request, HttpStatus.INTERNAL_SERVER_ERROR, TypeEnum.S); } @Override protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { ErrorModel error = exceptionMapping(ex, (ServletWebRequest) request, status, TypeEnum.S); return new ResponseEntity<>(error, headers, status); } private ErrorModel exceptionMapping(Exception e, ServletWebRequest request, HttpStatus status, TypeEnum type) { /* build and returns the error view */ } }

响应:POST http://localhost:8080/.../my-end-point

status 403
  

此响应具有错误的格式和状态代码!

预期:响应{ "timestamp": "2019-05-30T15:44:36.021-0400", "status": 403, "error": "Forbidden", "message": " Forbidden", "path": "/.../my-end-point" } ,根据ErrorModel类格式化。

Ex(具有“云”配置文件):

status: 405

响应:POST http://localhost:8080/.../my-end-point

status 405
  

此回复具有正确的格式和状态代码。这是期望和要求的!

当在本地配置文件中时,如何确保对POST的POST(或GET以外的任何其他方法)返回405错误?再次强调一下,当应用程序在“云”配置文件中运行时,一切都会按预期运行。

0 个答案:

没有答案