基于SpringAOP思想的拦截器,摒弃了InterceptorAdapter

每次当涉及到权限验证的时候,大家最先想到的就是基于SpringMVC的InterceptorAdapter拦截器来进行基础的权限验证,但是这个拦截器有这样一个问题,就是默认会拦截所有的请求,那么这个时候我们就可以基于AOP的思想,那些地方需要被拦截,只要关注这些地方就行了。下面直接上代码

基础技术 SpringBoot+JWT
pom文件如下:

		<dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.0</version>
        </dependency>
        <!-- SpringBoot 拦截器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.9.5</version>
        </dependency>

下面开始代码
1.AnnotationUtils工具类

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
 * 获取注解工具类
 *
 * @author wuhx 2020-05-15 09:23
 */
public class AnnotationUtils {
    private static final Log log = LogFactory.get();

    /**
     * 获取方法上的注解
     *
     * @param method     执行方法
     * @param annotation 注解的class
     * @return 返回注解实现对象, 如果没有, 则返回null
     */
    public static <T extends Annotation> T getAnnotation(Method method, Class<T> annotation) {
        if (method != null) {
            try {
                return method.getAnnotation(annotation);
            } catch (Exception e) {
                log.error(("获取方法上注解异常"), e);
                return null;
            }
        }

        return null;
    }

    /**
     * 获取类上的注解
     *
     * @param aClass     执行方法
     * @param annotation 注解的class
     * @return 返回注解实现对象, 如果没有, 则返回null
     */
    @SuppressWarnings("unchecked")
    public static <A extends Annotation> A getClassAnnotation(Class aClass, Class<A> annotation) {
        if (aClass != null) {
            try {
                return (A) aClass.getAnnotation(annotation);
            } catch (Exception e) {
                log.error(("获取类上注解异常"), e);
                return null;
            }
        }

        return null;
    }

    /**
     * 获取属性上的注解
     *
     * @author wuhx 2020-05-15 09:25
     */
    public static <T extends Annotation> T getFieldAnnotation(Class aClass, Class<T> annotation, String name) {
        try {
            return aClass.getDeclaredField(name).getAnnotation(annotation);
        } catch (NoSuchFieldException e) {
            return null;
        }
    }

}

2.AspectUtils工具类

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
 * @author wuhx 22020-05-15 09:23
 */
public class AspectUtils {

    /**
     * 获取织入点所在的方法
     *
     * @param point 织入点
     * @return 方法
     */
    public static Method getMethod(ProceedingJoinPoint point) {
        Signature signature = point.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        return methodSignature.getMethod();
    }

    /**
     * 获取织入点所在的类
     *
     * @param point 织入点
     * @return 类
     */
    public static Class getClass(ProceedingJoinPoint point) {
        return getMethod(point).getDeclaringClass();
    }

    /**
     * 获取执行织入点上的注解
     *
     * @param point      执行织入点
     * @param annotation 注解的class
     * @return 返回注解实现对象, 如果没有, 则返回null
     */
    public static <T extends Annotation> T getAnnotation(ProceedingJoinPoint point, Class<T> annotation) {
        return AnnotationUtils.getAnnotation(getMethod(point), annotation);
    }

    /**
     * 获取执行方法的类上的注解,如果方法上拥有相同注解,则以方法上的为准,
     *
     * @param point      执行织入点
     * @param annotation 注解的class
     * @return 返回注解实现对象, 优先返回方法上的,  如果没有, 返回类上的 ,如果没有 则返回null
     */
    public static <T extends Annotation> T getClassAnnotation(ProceedingJoinPoint point, Class<T> annotation) {
        Method method = getMethod(point);
        Class aClass = method.getDeclaringClass();

        T t = AnnotationUtils.getAnnotation(method, annotation);
        // 如果方法上没有相同注解,则返回类上的注解
        if (t == null) {
            return AnnotationUtils.getClassAnnotation(aClass, annotation);
        }
        return t;
    }
}

3.自定义注解

/**
 * @author wuhx  2020-05-12 14:12:19
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface TokenApp {
    // 是否校验token 默认true 进行token校验
    boolean value() default true;
}

4.定义拦截

/**
 * @author wuhx  2020-05-12 15:04:42
 */
@Aspect
@Order
@ControllerAdvice
public class TokenAppAspect {

    private final Audience audience;
    private final HttpServletRequest request;
    public TokenAppAspect(Audience audience,HttpServletRequest request) {
        this.audience = audience;
        this.request = request;
    }

    @Pointcut("@annotation(zhiyan.applets.base.annotation.TokenApp) || @within(zhiyan.applets.base.annotation.TokenApp)")
    public void pointcut(){}

    @Around("pointcut()")
    public Object filter(ProceedingJoinPoint point) throws Throwable{
        return check(point, AspectUtils.getClassAnnotation(point, TokenApp.class));
    }

    private Object check(ProceedingJoinPoint point, TokenApp tokenApp) throws Throwable{
        if (tokenApp != null && tokenApp.value()){
            String token = request.getHeader("token");
            //token为空
            if (StrUtil.isEmpty(token) || "null".equals(token)){
                return HttpResult.error("token为空");
            }
            if (JwtTokenUtil.isExpiration(token,audience.getBase64Secret())){
                return HttpResult.error("token过期");
            }
        }
        return point.proceed();
    }

}

下面,来看我们的Controller
只要在方法上加上@TokenAPP注解,那么这个方法就会进行校验。如果整个controller里面的方法都需要进行token校验,那么只要在类上 加上@TokenAPP注解即可。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值