![](/img/trans.png)
[英]How to handle run time exceptions thrown by Spring Security AuthenticationProviders?
[英]How to catch the exceptions thrown by spring security matchers?
我有一个受弹簧安全性保护的后端,该安全性由antMatchers()
配置,如.antMatchers("/api/myProtectedUri/*").authenticated()
在同一应用中,我使用@ControllerAdvice
和@ExceptionHandler
来处理引发的异常。 为了防止API从后端返回不受控制的响应(例如stacktraces),我编写了以下内容:
@ExceptionHandler({RuntimeException.class})
public ResponseEntity handleRuntimeException() {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Unexpected error occurred");
}
这导致测试失败,因为处理程序在保护端点的同时可能还捕获了Spring安全性引发的异常,状态码为500(来自处理程序),而不是预期的401或403(来自Spring)。
我尝试使用自定义处理程序,例如:
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler())
它仍然被带有RuntimeException子句的@ExceptionHandler捕获。
我的问题是:
Spring安全性基于过滤器,而Spring MVC基于servlet, @ExceptionHandler
不应捕获Spring安全性引发的异常。
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler())
这是一个ExceptionTranslationFilter
,它将处理AuthenticationException
和AccessDeniedException
,源代码请参见此处
Throwable[] causeChain = this.throwableAnalyzer.determineCauseChain(var10);
RuntimeException ase = (AuthenticationException)this.throwableAnalyzer.getFirstThrowableOfType(AuthenticationException.class, causeChain);
if (ase == null) {
ase = (AccessDeniedException)this.throwableAnalyzer.getFirstThrowableOfType(AccessDeniedException.class, causeChain);
}
if (ase == null) {
if (var10 instanceof ServletException) {
throw (ServletException)var10;
}
if (var10 instanceof RuntimeException) {
throw (RuntimeException)var10;
}
throw new RuntimeException(var10);
}
if (response.isCommitted()) {
throw new ServletException("Unable to handle the Spring Security Exception because the response is already committed.", var10);
}
this.handleSpringSecurityException(request, response, chain, (RuntimeException)ase);
AuthenticationException
(通常表示未通过AuthenticationEntryPoint
验证)将由AuthenticationEntryPoint
处理,您可以实现自己的AuthenticationEntryPoint
,只需覆盖commence
方法,例如HttpStatusEntryPoint
,它只会返回具有客户状态的响应。
public final class HttpStatusEntryPoint implements AuthenticationEntryPoint {
private final HttpStatus httpStatus;
public HttpStatusEntryPoint(HttpStatus httpStatus) {
Assert.notNull(httpStatus, "httpStatus cannot be null");
this.httpStatus = httpStatus;
}
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.setStatus(this.httpStatus.value());
}
}
您可以将入口点设置为异常处理。
exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
AccessDeniedHandler
(通常表示未授权)将由您完成的AccessDeniedHandler
处理。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.