前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用注解的方式+AOP校验签名

使用注解的方式+AOP校验签名

作者头像
用户5927264
发布2021-09-08 14:58:44
9680
发布2021-09-08 14:58:44
举报
文章被收录于专栏:OSChinaOSChina

1.定义注解 @CheckSign :

package com.un.framework.aspectj.lang.openapi;

import java.lang.annotation.*;

/**
 * 校验签名
 *
 * @author shiye
 */
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CheckSign {
    /**
     * 模块
     */
    public String title() default "";

}

2.定义基础请求对象,用来需要检验签名的参数基础类

子类需要继承改方法,并且重写你需要校验签名的参数

tranceToStr()
package com.un.project.system.domain.other;

import io.swagger.annotations.ApiModelProperty;

import javax.validation.constraints.NotNull;
import java.io.Serializable;

/**
 * @author shiye
 * @create 2021-08-16 13:45
 */
public class BaseRequestParm implements Serializable {

    /**
     * appId
     */
    @ApiModelProperty(value = "appId")
    @NotNull(message = "appId不能为空")
    protected String appId;

    /**
     * 签名
     */
    @ApiModelProperty(value = "签名")
    @NotNull(message = "sign不能为空")
    protected String sign;

    public String getAppId() {
        return appId;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }

    public String getSign() {
        return sign;
    }

    public void setSign(String sign) {
        this.sign = sign;
    }

    /**
     * 按key的升序排列首尾相接(出了sigin字段)
     * 子类方法需要实现改方法
     * @return
     */
    public String tranceToStr() {
        StringBuffer strBuff = new StringBuffer();
        strBuff.append("appId");
        strBuff.append(appId);
        return strBuff.toString();
    }
}

3. 定义AOP环绕通知拦截信息

package com.un.framework.aspectj.lang.openapi;

import com.un.common.utils.security.Md5Utils;
import com.un.project.system.controller.app.BaseResult;
import com.un.project.system.domain.other.BaseRequestParm;
import com.un.project.system.domain.other.CommunityInfoParams;
import com.un.project.system.domain.other.QueryHouseChangeVo;
import com.un.project.system.domain.other.StructAndUserInfoParams;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * 签名校验处理
 *
 * @author shiye
 */
@Aspect
@Component
public class CheckSignAspect {

    private static final String secret_key = "CRVFSMQA3P2ZKIBU5NOVY9YKH6O1TXPI";
    private static final Logger log = LoggerFactory.getLogger(CheckSignAspect.class);

    /**
     * 配置织入点
     */
    @Pointcut("@annotation(com.un.framework.aspectj.lang.openapi.CheckSign)")
    public void logPointCut() {
    }

    /**
     * 环绕通知
     *
     * @param point 切点
     */
    @Around("logPointCut()")
    public BaseResult doAfterThrowing(ProceedingJoinPoint point) throws Throwable {
        Boolean flag = beforHandleSign(point);
        log.info("签名校验状态: " + flag);
        if (flag == true) {
            return (BaseResult) point.proceed();
        }
        return BaseResult.buildFail("签名校验失败");
    }

    /**
     * 前置通知处理
     *
     * @param joinPoint
     */
    protected Boolean beforHandleSign(ProceedingJoinPoint joinPoint) {
        try {
            /**
             * 获得注解
             */
            CheckSign checkSign = getAnnotationCheckSign(joinPoint);
            if (checkSign == null) {
                return false;
            }
            //获取拦截方法的参数
            Object[] params = joinPoint.getArgs();
            if (params == null || params.length == 0) {
                return false;
            }
            //获取请求参数
            Object obj = params[0];
            //根据不同的请求参数进行验签
            if (obj instanceof BaseRequestParm) {
                BaseRequestParm baseRequestParm = (BaseRequestParm) params[0];
                if (baseRequestParm == null) {
                    return false;
                }
                String tranceToStr = baseRequestParm.tranceToStr();
                String beforSign = secret_key + tranceToStr + secret_key;
                String sign = Md5Utils.hash(beforSign).toUpperCase();
                log.info(" ==== 本系统加签值 ==== " + sign);
                if (sign != null && sign.equals(baseRequestParm.getSign().toUpperCase())) {
                    return true;
                }
            }

        } catch (Exception exp) {
            // 记录本地异常日志
            log.error("==前置通知异常==");
            log.error("异常信息:{}", exp.getMessage());
            exp.printStackTrace();
        }
        return false;
    }

    /**
     * 是否存在注解,如果存在就获取
     */
    private CheckSign getAnnotationCheckSign(JoinPoint joinPoint) throws Exception {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method != null) {
            return method.getAnnotation(CheckSign.class);
        }
        return null;
    }

    /**
     * 判断是否需要过滤的对象。
     *
     * @param o 对象信息。
     * @return 如果是需要过滤的对象,则返回true;否则返回false。
     */
    public boolean isFilterObject(final Object o) {
        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse;
    }
}

4.调用方式 (只需要一行代码就可以轻轻松松的进行拦截,想拦截哪就拦截哪) : @CheckSign(title = "****")

    @PostMapping("/changeData")
    @CheckSign(title = "****")
    public BaseResult<HouseChangeDto> changeData(@RequestBody @Validated QueryHouseChangeVo queryHouseChangeVo) {
        
        return null;
    }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档