@PostAuthorize失败时返回404而不是403

时间:2020-03-23 10:30:13

标签: java spring spring-security

假设我有以下控制器。 (假设Order.customer是订单所属的客户,只有他们才能访问该订单。)

@RestController
@RequestMapping("/orders")
public class OrderController {
    @GetMapping
    @PostAuthorize("returnObject.customer == authentication.principal")
    public Order getOrderById(long id) {
        /* Look up the order and return it */
    }
}

查询订单后,@PostAuthorize用于确保其属于已认证的客户。如果不是,那么Spring会以403 Forbidden进行响应。

这样的实现存在一个问题:客户可以区分不存在的订单和无法访问的订单。理想情况下,在两种情况下均应返回404。

虽然可以通过将Authentication注入到处理程序方法中并在其中实现自定义逻辑来解决此问题,但是有什么方法可以使用@PostAuthorize或类似的声明性API来实现?

2 个答案:

答案 0 :(得分:1)

您可以尝试使用ControllerAdvice来捕获和转换PostAuthorize引发的AccessDeniedException。

@RestControllerAdvice
public class ExceptionHandlerController {

    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(AccessDeniedException.class)
    public String handleAccessDenied(AccessDeniedException e) {
        return "nothing here"; // or a proper object
    }
}

答案 1 :(得分:1)

您可以在Spring Security配置中指定自定义AccessDeniedHandler
在以下示例中,处理程序将在拒绝访问失败时返回404 Not Found。

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                // ...
                .exceptionHandling(exceptionHandling -> exceptionHandling
                        .accessDeniedHandler(accessDeniedHandler())
                );
    }

    @Bean
    public AccessDeniedHandler accessDeniedHandler() {
        return new CustomAccessDeniedHandler();
    }
}
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
        response.sendError(HttpStatus.NOT_FOUND.value(), HttpStatus.NOT_FOUND.getReasonPhrase());
    }
}