我在Sping Boot 应用程序中实现了Spring Security,默认情况下,它会正确地抛出401(未经授权)或403(禁止),这样下面的单元测试就可以工作了:
@Test
void notLoggedIn() throws Exception {
mockMvc.perform(get("/service")) //
.andExpect(status().isUnauthorized()); // 401 is returned and caught
}
void loggedInWithIncorrectRole() throws Exception {
mockMvc.perform(get("/service").with(user("someuser").roles("invalidRole"))) //
.andExpect(status().isForbidden()); // 403 is returned and caught
}
字符串
然后我添加了一个@ControllerAdvice
全局ExceptionHandler
来捕获应用程序抛出的所有异常。现在,所有的安全异常都以org.springframework.security.access.AccessDeniedException: Access Denied
的形式出现在ExceptionHandler
中。在这个异常中,401和403都被合并了。
@ControllerAdvice
public class AppExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(Exception e, WebRequest request) {
log.error(e);
if ("org.springframework.security.access.AccessDeniedException".equals(e.getClass().getName())) {
// This will catch BOTH 401 and 403, no distinction
return new ResponseEntity<ErrorResponse>(HttpStatus.UNAUTHORIZED);
} else {
return ResponseEntity.internalServerError()
.body(new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, "Error occurred));
}
}
型
堆栈跟踪总是
org.springframework.security.access.AccessDeniedException: Access Denied
at org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor.attemptAuthorization(AuthorizationManagerBeforeMethodInterceptor.java:256)
at org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor.invoke(AuthorizationManagerBeforeMethodInterceptor.java:197)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:717)
型
如何区分?
1条答案
按热度按时间7gcisfzg1#
@ControllerAdvice
无法处理BadCredentialsException
,当没有找到用户或不正确的凭据时会抛出BadCredentialsException
,因为尚未调用控制器方法。在这种情况下,
BasicAuthenticationEntryPoint
会被触发。如果你想记录所有失败的尝试,你可以创建一个自定义入口点,如下所示:字符串
确保正确配置:
型