【自定义注解+AOP实现登录校验+全局异常处理返回友好提示】

步骤

1.自定义注解 @CheckLogin

package com.itmuch.usercenter.auth;

/**
 * 校验登录的注解
 * @author mikasa
 */
public @interface CheckLogin {
    
    
}

2.对要拦截的方法加上@CheckLogin注解

@GetMapping("/{id}")
@CheckLogin
public User findById(@PathVariable Integer id) {
    
    
        log.info("我被请求了...");
        return this.userService.findById(id);
}

3.定义切面拦截校验

/**
 * 登录拦截切面
 * @author mikasa
 */
@Aspect
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AuthAspect {
    
    
  
  /**
     * 校验token的工具类
     */
    private final JwtOperator jwtOperator;

    @Around("@annotation(com.itmuch.usercenter.auth.CheckLogin)")
    public Object checkLogin(ProceedingJoinPoint point) throws Throwable {
    
    
        checkToken();
        return point.proceed();
    }

    private void checkToken() {
    
    
        try {
    
    
            // 1. 从header里面获取token
            HttpServletRequest request = getHttpServletRequest();

            String token = request.getHeader("X-Token");

            // 2. 校验token是否合法&是否过期;如果不合法或已过期直接抛异常;如果合法放行
            Boolean isValid = jwtOperator.validateToken(token);
            if (!isValid) {
    
    
                throw new SecurityException("Token不合法!");
            }

            // 3. 如果校验成功,那么就将用户的信息设置到request的attribute里面
            Claims claims = jwtOperator.getClaimsFromToken(token);
            request.setAttribute("id", claims.get("id"));
            request.setAttribute("wxNickname", claims.get("wxNickname"));
            request.setAttribute("role", claims.get("role"));
        } catch (Throwable throwable) {
    
    
            throw new SecurityException("Token不合法");
        }
    }

    /**
     * RequestContextHolder静态方法获取RequestAttributes
     * @return HttpServletRequest
     */
    private HttpServletRequest getHttpServletRequest() {
    
    
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;
        return attributes.getRequest();
    }

4.失败返回异常提示处理

package com.itmuch.usercenter.auth;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * @author mikasa
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionErrorHandler {
    
    
    @ExceptionHandler(SecurityException.class)
    public ResponseEntity<ErrorBody> error(SecurityException e) {
    
    
        log.warn("发生SecurityException异常", e);
        return new ResponseEntity<>(
            ErrorBody.builder()
                .body(e.getMessage())
                .status(HttpStatus.UNAUTHORIZED.value())
                .build(),
            HttpStatus.UNAUTHORIZED
        );
    }
}



@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
class ErrorBody {
    
    
    private String body;
    private int status;
}

知识点

@annotation

概念:是一个AspectJ切点函数,它可以用于匹配带有指定注解的方法

用法:@annotation(自定义注解的全限定名/xxx.class)

@Around("@annotation(com.mikasa.usercenter.auth.CheckLogin/CheckLogin.class)")
public Object checkLogin(ProceedingJoinPoint joinPoint) throws Throwable {
    
    
    // ...
}

回忆切点表达式:

execution([访问控制权限修饰符] 返回值类型 [全限定类名]方法名(形式参数列表) [异常])

// controler包下的所有以Controller结尾的类的任意方法
@Around("execution(* com.mikasa.usercenter.controller.*Controller.*(..))

RequestContextHolder

概念:是一个Spring框架提供的工具类,它可以用于获取当前请求的上下文信息。

API: 静态方法getRequestAttributes(),它可以用于获取当前请求的ServletRequestAttributes对象。

ServletRequestAttributes: 包含了当前请求的所有信息,例如请求头、请求参数、请求体等

private HttpServletRequest getHttpServletRequest() {
    
    
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;
        return attributes.getRequest();
    }

@RestControllerAdvice

概念:Spring框架中的一个注解,用于定义一个全局的异常处理器。当Web服务中发生异常时,@RestControllerAdvice注解的类可以处理异常并返回HTTP响应。

使用:使用@RestControllerAdvice注解的类可以包含多个方法,每个方法都可以处理不同的异常类型。这些方法应该使用**@ExceptionHandler**注解来声明处理的异常类型。

意义:在处理异常时,@RestControllerAdvice类可以返回自定义的HTTP响应或其他类型的响应体,例如JSON或XML。这使得开发人员可以在发生异常时向客户端提供更有意义的响应,而不仅仅是简单的错误消息。

猜你喜欢

转载自blog.csdn.net/weixin_52156647/article/details/129708588