使用 @restcontrolleradvice 配合 @exceptionhandler 可以统一捕获权限校验异常。核心做法是定义一个全局异常处理器类,在其中编写处理特定权限异常(如 accessdeniedexception)的方法,并标注 @exceptionhandler 指定要捕获的异常类型,该方法返回自定义的响应体对象即可。

如何配置全局异常处理器类
需要创建一个继承自 ControllerAdvice 的类,并使用 @RestControllerAdvice 注解使其生效。该类会自动扫描所有 Controller 抛出的异常。在类内部,定义一个方法专门处理权限相关的异常,例如 Spring Security 中的 AccessDeniedException。通过 @ExceptionHandler(AccessDeniedException.class) 注解绑定异常类型,方法参数中直接注入该异常对象,Spring 会自动将抛出的异常传入。方法返回值应设置为 ResponseEntity 或自定义的 JSON 结构,以便前端能解析错误信息。

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<string> handleAccessDenied(AccessDeniedException ex) {
return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body("权限不足: " + ex.getMessage());
}
}</string>
上述代码定义了全局处理器,当控制器抛出 AccessDeniedException 时,会拦截并返回 403 状态码及提示信息。确保该类在 Spring Boot 启动类的包路径下或被显式扫描到,否则不会生效。
如何处理未认证的访问异常
除了权限不足,未登录或 Token 失效通常抛出 AuthenticationException 或其子类 BadCredentialsException。这类异常应在同一个或不同的全局处理器中单独捕获,以区分“没资格”和“没身份”。处理方式与权限异常类似,但返回的状态码通常为 401 Unauthorized。可以在 @RestControllerAdvice 类中添加另一个 @ExceptionHandler 方法来处理此类异常,或者创建专门的认证异常处理器类。关键是要明确区分这两种异常的业务含义,避免混淆用户提示。

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.AuthenticationException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class AuthExceptionHandler {
@ExceptionHandler(AuthenticationException.class)
public ResponseEntity<string> handleAuthError(AuthenticationException ex) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body("认证失败: 请重新登录");
}
}</string>
此段代码展示了如何处理认证异常。当用户未提供有效凭证时,系统会返回 401 状态码。注意,AuthenticationException 是更广泛的父类,实际项目中可能还需要细化处理如 ExpiredJwtException 等具体场景。保持异常处理的粒度清晰有助于前端进行不同的 UI 反馈,如跳转登录页或弹出重登提示。
当自定义权限检查逻辑抛出 RuntimeException 时如何处理
如果在业务代码中手动进行权限判断并抛出通用的 RuntimeException,全局异常处理器同样可以捕获。只需在 @RestControllerAdvice 中添加针对 RuntimeException 的处理方法,或在更具体的自定义异常类上添加处理方法。建议在业务层定义专用的权限异常类,如 BusinessPermissionException,继承自 RuntimeException,并在全局处理器中专门捕获它,这样比捕获通用异常更安全、更清晰。通过这种方式,可以将业务逻辑中的权限校验与框架层的权限校验统一纳入全局管理,确保所有权限问题都能得到一致的错误响应格式。











