将 AccessDeniedException 传播到 Spring Security 3.2
Posted
技术标签:
【中文标题】将 AccessDeniedException 传播到 Spring Security 3.2【英文标题】:Propagate AccessDeniedException to 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
注释的异常处理程序,并带有一个捕获Exception
的ExceptionHandler
方法,因此AccessDeniedException 不会传播到Spring Security ExceptionResolvingFilter
;因此,它不是由 Spring Security 处理的。
我尝试遵循here 的建议并创建了另一个专门处理AccessDeniedException
的ExceptionHandler
方法并简单地重新抛出它。但是这个例外再次没有弥补 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
并继承并重写该方法吗?
【问题讨论】:
【参考方案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());
【讨论】:
以上是关于将 AccessDeniedException 传播到 Spring Security 3.2的主要内容,如果未能解决你的问题,请参考以下文章
写入 JCR (JackRabbit) [Magnolia] 时出现 AccessDeniedException
由于错误 AccessDeniedException(Lambda 别名作为 Cognito 触发器),AWS Cognito 用户池引发 PreSignUp 调用失败
gsutil cors set 命令返回 403 AccessDeniedException
AccessDeniedException 上的 HTTP 401 [重复]
AccessDeniedException:用户无权对资源执行 dynamodb BatchWriteItem:表
收到 Spring MVC AccessDeniedException 500 错误,而不是 @PreAuthorized 未授权请求的自定义 401 错误