【问题标题】:Propagate AccessDeniedException to Spring Security 3.2将 AccessDeniedException 传播到 Spring Security 3.2
【发布时间】:2015-09-04 16:39:48
【问题描述】:

我在 Spring Security 3.2 和 Spring 4.1.7 (Boot 1.2.5) 中使用全局方法安全性。 Spring 的全局方法安全拦截器抛出AccessDeniedException。但是,我有一个用@ControllerAdvice 注释的异常处理程序,并带有一个捕获ExceptionExceptionHandler 方法,因此AccessDeniedException 不会传播到Spring Security ExceptionResolvingFilter;因此,它不是由 Spring Security 处理的。

我尝试遵循here 的建议并创建了另一个专门处理AccessDeniedExceptionExceptionHandler 方法并简单地重新抛出它。但是这个例外再次没有弥补 Spring Security 的问题。它在第 366 行被 Spring 的 ExceptionHandlerExceptionResolver 吞噬:

// ============ SPRING'S EXCEPTIONHANDLEREXCEPTIONRESOLVER CODE ==========
try {
    if (logger.isDebugEnabled()) {
        logger.debug("Invoking @ExceptionHandler method: " + exceptionHandlerMethod);
    }
    exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception);
}
catch (Exception invocationEx) {
    if (logger.isErrorEnabled()) {
        logger.error("Failed to invoke @ExceptionHandler method: " + exceptionHandlerMethod, invocationEx);
    }
    return null;
}

如何让AccessDeniedException 传播到 Spring Security?我必须创建一个自定义 ExceptionResolver 并继承并重写该方法吗?

【问题讨论】:

    标签: spring spring-mvc spring-security


    【解决方案1】:

    您的代码吞下了异常

    catch (Exception invocationEx) {
        if (logger.isErrorEnabled()) {
            logger.error("Failed to invoke @ExceptionHandler method: " + exceptionHandlerMethod, invocationEx);
        }
        return null; // here is the culprit
    }
    

    最好只是记录它或重新抛出它

    catch (Exception invocationEx) {
        if (logger.isErrorEnabled()) {
            logger.error("Failed to invoke @ExceptionHandler method: " + exceptionHandlerMethod, invocationEx);
        }
        throw invocationEx;
    }
    

    【讨论】:

    • 这就是问题所在:这不是我的代码,而是 Spring 的。 ExceptionHandlerExceptionResolver,第 366 行。
    【解决方案2】:

    最后,我要做的就是在@ControllerAdvice 类中添加一个方法:

    @ExceptionHandler(AccessDeniedException.class)
    public ResponseEntity<WebServiceResponse> handleAccessDeniedException(AccessDeniedException ex)
    {
        WebServiceResponse response = new WebServiceResponseWithError(status: 'failure', message: ex.message, errorCode: 1007)
        return new ResponseEntity(response, HttpStatus.FORBIDDEN)
    }
    

    WebServiceResponse 是我为构建响应而编写的一个类。

    这行得通,虽然我在模仿 Spring 的异常处理......

    【讨论】:

      【解决方案3】:

      您也可以通过在@ControllerAdvice 类中添加以下代码来设置响应对象中的错误。

        @ExceptionHandler (value = {AccessDeniedException.class})
        public void commence(HttpServletRequest request, HttpServletResponse response,
            AccessDeniedException accessDeniedException) throws IOException {
          response.sendError(HttpStatus.FORBIDDEN, accessDeniedException.getMessage());
        } 
      

      【讨论】:

        猜你喜欢
        • 2013-04-10
        • 2017-06-14
        • 1970-01-01
        • 2013-07-05
        • 2014-05-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-25
        相关资源
        最近更新 更多