这篇文章主要探讨security在认证失败和权限不足时抛出异常的时机。
使用了ControllerAdvice统一异常处理后,security抛出的异常,有些被security的异常处理器捕获,而有些被ControllerAdvice捕获。
在这之前需要明白security认证和权限校验的时机。
对于一个需要认证或权限的api,它的处理流程如下。
为了方便我把ExceptionTranslationFilter称为异常过滤器,把FilterSecurityInterceptor成为security处理器
- 当发送请求时,在token过滤器中会将请求所拥有的权限放入security上下文中。
- 执行到security处理器时,对用户进行认证和权限校验。
- 如果认证失败,这里会抛出AccessDeniedException异常,被 异常过滤器捕获,而后调用security的认证失败处理器AuthenticationEntryPoint。异常捕获后就不会再抛出了。至此请求返回。(程序不会报错信息)。
- 如果认证成功,security处理器进入权限验证阶段,调用所访问的api,通过该api的切面去验证请求是否有权限访问对应该api。
- 权限验证成功,切面放行。
- 权限验证失败也会抛出AccessDeniedException异常(是的,认证失败和权限不足都是这个异常,校验的方法也是同一个,AffirmativeBased的decide方法)。因为这时是调用api切面实现的权限校验,所以这里抛出的异常会被ControllerAdvice拦截,如果没有配置ControllerAdvice,异常会被异常过滤器捕获,而后调用security的拒绝访问处理器。(内部通过请求是否匿名来判断应该调用哪个处理器)。
- 请求结束。
总结一下,认证操作是在进入控制层之前完成,抛出的异常也是在控制层之前抛出。权限校验操作是在进入控制层之后,api执行之前完成,异常是在进入控制层之后抛出。
所以,在不配置ControllerAdvice情况下,认证失败和拒绝访问都会调用security对应的处理器。当配置ControllerAdvice后,拒绝访问异常会先经过ControllerAdvice,如果被捕获,则不会再调用security处理器。