自定义注解实现

我们想在项目的一些接口上增加权限校验的功能,最方便的方式就是通过AOP切面的方式。这里我们利用自定义自定义注解的方式来实现这一功能

  1. 首先自定义一个注解

@Retention(value = RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface SignatureValidation {
}

  1. 在需要验证的controller上使用该注解

@RestController
@RequestMapping
@SignatureValidation
public class ChainOrgController {
}
  1. 利用切进行对权限进行校验,这里我们介绍两种方式

a. 使用AspectJ的方式

@Aspect
@Component
@Slf4j
public class SignatureValidationAop {
    private static final Map<String, String> map = new HashMap<>();
    /**
     * 时间戳请求最大限制
     */
    private static final long MAX_REQUEST = 30 * 1000L;

    @PostConstruct
    public void init(){
        System.out.println("系统启动中。。。加载map");
    }
    /*
     * 验签切点
     */
    @Pointcut("@within(com.test.SignatureValidation)")//有SignatureValidation注解的类,也可以兼容方法级别需要增加切点范围https://blog.csdn.net/sunlihuo/article/details/52701548
    private void verifyUserKey() {
    }
    /**
     * 开始验签
     */
    @Before("verifyUserKey()")
    public void doBasicProfiling() {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        String token = request.getHeader("token");
        String timestamp = request.getHeader("timestamp");
        String orgId = request.getHeader("orgId");

        try {
            Boolean check = checkToken(token, timestamp, orgId);
            if (!check) {
                throw new RuntimeException("验签失败!");
            }
        } catch (Throwable throwable) {
            throw new RuntimeException("验签失败!");
        }
    }
    /**
     * 校验token
     *
     * @param token     签名
     * @param timestamp 时间戳
     * @return 校验结果
    */
    private Boolean checkToken(String token, String timestamp, String orgId) {
        log.info("checktoken:{},{},{}", token, timestamp, orgId);
        if (StringUtils.isAnyBlank(token, timestamp)) {
            return false;
        }
        long now = System.currentTimeMillis();
        long time = Long.parseLong(timestamp);
        if (now - time > MAX_REQUEST) {
            return false;
        }
        String secret = map.get(orgId);
        String crypt = MD5Utils.getMD5(secret + orgId + timestamp);
        return StringUtils.equals(crypt, token);
    }
}

b. 实现HandlerInterceptor

@Slf4j
public class SignValidateInterceptor implements HandlerInterceptor {
    private static final Map<String, String> map = new HashMap<>();
    /**
     * 时间戳请求最大限制
     */
    private static final long MAX_REQUEST = 30 * 1000L;

    @PostConstruct
    public void init(){
        System.out.println("系统启动中。。。加载codeMap");
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        boolean flag = true;
        if (handler instanceof HandlerMethod) {
            // 访问的是接口方法,转化为待访问的目标方法对象
            HandlerMethod targetMethod = (HandlerMethod) handler;
            // 获取目标接口方法所在类的注解@AccessLimit
            SignatureValidation targetClassAnnotation = targetMethod.getMethod().getDeclaringClass().getAnnotation(SignatureValidation.class);

            if (!Objects.isNull(targetClassAnnotation)) {
                String token = request.getHeader("token");
                String timestamp = request.getHeader("timestamp");
                String orgId = request.getHeader("orgId");
                flag = checkToken(token, timestamp, orgId);
                if(!flag){
                    throw new CommonException("权限校验出错,请重试!");
                }
            }

        }
        return true;
    }

    private Boolean checkToken(String token, String timestamp, String orgId) {
        log.info("checktoken:{},{},{}", token, timestamp, orgId);
        if (StringUtils.isAnyBlank(token, timestamp)) {
            return false;
        }
        long now = System.currentTimeMillis();
        long time = Long.parseLong(timestamp);
        if (now - time > MAX_REQUEST) {
            return false;
        }
        String secret = map.get(orgId);
        String crypt = MD5Utils.getMD5(secret + orgId + timestamp);
        return StringUtils.equals(crypt, token);
    }
}

使用这种方式需要把拦截器在WebConfiguration注册,定义拦截规则

@Configuration
public class WebConfiguration implements WebMvcConfigurer {

    @Bean
    public SignValidateInterceptor createSignValidateInterceptor(){
        return new SignValidateInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(createSignValidateInterceptor())
                .addPathPatterns("/**");
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值