【自定义注解+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。这使得开发人员可以在发生异常时向客户端提供更有意义的响应,而不仅仅是简单的错误消息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mikasa_akm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值