SpringBoot使用AOP、JWT完成权限管理

admin 130 0

添加依赖

<dependency>
   <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
    <version>2.1.6.RELEASE</version>
</dependency>

自定义注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
   
//用来跳过验证的PassToken
 @Target({ElementType.METHOD, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
 public @interface PassToken {
     boolean required() default true;
 }

注解更多的作用是标记,方便我们后续AOP检查需要处理的方法

  • Target注解说明如下

@Target 注解的作用目标
@Target(ElementType.TYPE)——接口、类、枚举、注解
@Target(ElementType.FIELD)——字段、枚举的常量
@Target(ElementType.METHOD)——方法
@Target(ElementType.PARAMETER)——方法参数
@Target(ElementType.CONSTRUCTOR) ——构造函数
@Target(ElementType.LOCAL_VARIABLE)——局部变量
@Target(ElementType.ANNOTATION_TYPE)——注解
@Target(ElementType.PACKAGE)——包


AOP的代码如下

import club.web51.classroominteractiontoolsadmin.Enums.MsgEnum;
import club.web51.classroominteractiontoolsadmin.Exceptions.ErrDataException;
import club.web51.classroominteractiontoolsadmin.Repositories.UserRepository;
import club.web51.classroominteractiontoolsadmin.Services.UserService;
import club.web51.classroominteractiontoolsadmin.Utils.MsgUtil;
import club.web51.classroominteractiontoolsadmin.VO.TokenVO;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Classname TokenAop
 * @Description TODO 全局Token切面拦截处理(注解)
 * @Date 2020/11/20 0:01
 * @Created by HanYuHao
 */
@Component
@Aspect
@Slf4j
public class TokenAop {
    @Resource
    UserService userService;
    @Resource
    UserRepository userRepository;
    @Resource
    JwtUtil jwtUtil;
    private final Boolean isDebug = true;
    private Object[] args;

    
    //指定需要切面处理的包
    @Pointcut("execution(* club.web51.classroominteractiontoolsadmin.Controllers..*.*(..))")
    public void doHandler(){

    }

    @Around("doHandler()")
    public Object exception(ProceedingJoinPoint joinPoint){
        try{
            if(isDebug)
                outLog(joinPoint);
            //校验
            args = joinPoint.getArgs();
            beforePoint(joinPoint);
            //放行
            Object result = joinPoint.proceed(args);
            if(isDebug)
                log.info("结果:"+result);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            if(e instanceof ErrDataException){
                return MsgUtil.fail(e.getMessage());
            }else{
                return MsgUtil.fail();
            }
        } catch (Throwable e) {
            return MsgUtil.fail("系统异常");
        }
    }

    /**
     * 输出调试信息
     * @param joinPoint
     */
    private void outLog(ProceedingJoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        Object[] objects = joinPoint.getArgs();
        log.info("执行:" + methodName + "\n参数:"+ Arrays.toString(objects));
    }

    //执行前处理
    private Boolean beforePoint(ProceedingJoinPoint joinPoint){
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        //获取Token
        String token = request.getHeader("X-Token");
        //得到要进入的是哪个controller方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        if(method.isAnnotationPresent(NonRequireToken.class)){
            NonRequireToken nonRequireToken = method.getAnnotation(NonRequireToken.class);
            if(nonRequireToken.required()){
                return true;
            }
        }

        //注解是否存在+处理
        if(method.isAnnotationPresent(RequireToken.class)){
            RequireToken requireToken = method.getAnnotation(RequireToken.class);
            if(requireToken.required()){
                if(Objects.isNull(token) || "".equals(token)){
                    throw new ErrDataException(MsgEnum.ERROR_USER_DATA_INVAILD);
                }
                if(!jwtUtil.verify(token)){
                    throw new ErrDataException(MsgEnum.ERROR_USER_DATA_INVAILD);
                }
                Long uid = jwtUtil.getUid(token);

                TokenVO tokenVO = TokenVO.builder().token(token).uid(uid).build();

                Object[] objects = joinPoint.getArgs();
                for (int i = 0; i < objects.length; i++) {
                    if(objects[i] instanceof TokenVO){
                        objects[i] = tokenVO;
                    }
                }
                //入参修改后传回去
                args = objects;

            }
        }
        return true;
    }
}

大功告成

现在可以使用了!

发表评论 (已有0条评论)

还木有评论哦,快来抢沙发吧~