对返回ID加密处理返回方案

一,先创建注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IdEncrypt {

    /**
     * 是否需要对请求参数进行解密
     *
     * @return
     */
    boolean reqHandle();

    /**
     * 加密的参数位置
     *
     * @return
     */
    int reqEncryptIndex() default 0;

    String encryptPath() default "";

    /**
     * 解密的参数位置
     *
     * @return
     */
    int reqDecryptIndex() default 0;;

    boolean isObject() default false;


    /**
     * 返回结果处理 -(原id置空或置0处理)
     *
     * @return
     */
    String sourcePath();

    /**
     * 返回结果处理 - 加密后id的路径
     *
     * @return
     */
    String rewritePath();

    /**
     * 返回结果处理 - 加密后id的名称
     *
     * @return
     */
    //String rewriteParam();

    //业务类型:news,course,sms...
    BusinsTypeEnum type() ;

    /**
     * 看返回的data组装数据是list还是map格式的及是否需要加密unencrypt
     * @return
     */
    ReturnDataTypeEnum dataType();
}

二,创建切面拦截注解,处理自己的业务

@Aspect
@Component
@Slf4j
public class IdEncryptHandlerAspect {


    public static final String PASSWORD = "course:xcc:2022";

    //文章ID,大于这个ID的文章获取详情时都要进行解密操作
    public static final Long newsId = 6937225l;

    @Resource
    private EncryptBodyConfig config;

    @Pointcut("@annotation(com.dtguai.encrypt.annotation.encrypt.IdEncrypt)")
    public void pointCut() {

    }

    /**
     *  处理请求参数,转换为解密后的数据并覆盖请求参数
     * @param obj 请求参数
     * @param idEncryptHandler  注解类
     * @return
     */
    private Object[] dealRequestParamData(Object[] obj, IdEncrypt idEncryptHandler){
        //业务类型
        BusinsTypeEnum businsTypeEnum = idEncryptHandler.type();
        if(obj[idEncryptHandler.reqEncryptIndex()] instanceof Long ){//加密参数是Long类型
            Long encryptedId = (Long) obj[idEncryptHandler.reqEncryptIndex()];
                //如果是文章业务,直接用解密后的文章ID覆盖
                if(BusinsTypeEnum.NEWS.getType().equals(businsTypeEnum.getType())){
                    log.info("文章详情接口输入的加密id值为:"+encryptedId);
                    //String decryptedId = EncryptBodyMethod.DES.getISecurity().decrypt(String.valueOf(encryptedId), PASSWORD, config);
                    //不是百度seo收录的旧文章,都要解密UUID
                    if(encryptedId!= 0 && encryptedId < newsId){
                        obj[idEncryptHandler.reqDecryptIndex()] = encryptedId;
                    }else{
                        Long decryptedId = DeAndEnUtil.decrypt(Long.valueOf(String.valueOf(encryptedId)));
                        obj[idEncryptHandler.reqDecryptIndex()] = Long.valueOf(decryptedId);
                    }
                }else{
                    //String decryptedId = EncryptBodyMethod.DES.getISecurity().decrypt(String.valueOf(encryptedId), PASSWORD, config);
                    Long decryptedId = DeAndEnUtil.decrypt(Long.valueOf(String.valueOf(encryptedId)));
                    //if(obj[idEncryptHandler.reqDecryptIndex()] instanceof Integer){ //如果入参是 Integer 类型
                     //   obj[idEncryptHandler.reqDecryptIndex()] = decryptedId.intValue();
                  //  }else if(obj[idEncryptHandler.reqDecryptIndex()] instanceof Long){ //如果入参是 Long 类型
                        obj[idEncryptHandler.reqDecryptIndex()] =decryptedId;
                    //}
                }
        }else if(obj[idEncryptHandler.reqEncryptIndex()] instanceof Integer){//加密参数是Integer类型
            Integer encryptedId = (Integer) obj[idEncryptHandler.reqEncryptIndex()];
            //如果是文章业务,直接用解密后的文章ID覆盖
            if(BusinsTypeEnum.NEWS.getType().equals(businsTypeEnum.getType())){
                log.info("文章详情接口输入的加密id值为:"+encryptedId);
                //不是百度seo收录的旧文章,都要解密UUID
                if(encryptedId!= 0 && encryptedId < newsId.intValue()){
                    obj[idEncryptHandler.reqDecryptIndex()] = encryptedId;
                }else{
                    Long decryptedId = DeAndEnUtil.decrypt(encryptedId.longValue());
                    obj[idEncryptHandler.reqDecryptIndex()] = decryptedId.intValue();
                }
            }else{
                Long decryptedId = DeAndEnUtil.decrypt(encryptedId.longValue());
                obj[idEncryptHandler.reqDecryptIndex()] =decryptedId.intValue();
            }
        }else if(obj[idEncryptHandler.reqEncryptIndex()] instanceof List){//加密参数是List类型
            List<Long> ids = new ArrayList<Long>();
            //uuid参数集合
            List<Long> encryptedIds = (List) obj[idEncryptHandler.reqEncryptIndex()];
            //原ID参数集合
            List<Long>  orginIds =  (List)  (obj[idEncryptHandler.reqDecryptIndex()]) ;
            if (CollectionUtil.isNotEmpty(encryptedIds)) {
                for(int i= 0; i< orginIds.size(); i++){
                    //如果是文章业务,则判断是否是百度seo收录的旧文章访问,小于特定的旧文章,默认都是被百度seo收录
                    if(BusinsTypeEnum.NEWS.getType().equals(businsTypeEnum.getType())){
                        //不是百度seo收录的旧文章,都要解密UUID
                        if(orginIds.get(i) != 0 && orginIds.get(i) < newsId){
                            ids.add(orginIds.get(i));
                        }else{
                            log.info("文章详情接口输入的文章uuid值为:"+orginIds.get(i));
                            //String decryptedId = EncryptBodyMethod.DES.getISecurity().decrypt(String.valueOf(encryptedIds.get(i)), PASSWORD, config);
                            Long decryptedId = DeAndEnUtil.decrypt(orginIds.get(i));
                            ids.add(decryptedId);
                        }
                    }else{
                       // String decryptedId = EncryptBodyMethod.DES.getISecurity().decrypt(String.valueOf(encryptedIds.get(i)), PASSWORD, config);\
                        Long decryptedId = DeAndEnUtil.decrypt(orginIds.get(i));
                        ids.add(decryptedId);
                    }
                }
                //if(obj[idEncryptHandler.reqDecryptIndex()] instanceof Integer){
                  //  obj[idEncryptHandler.reqDecryptIndex()] = ids.stream().mapToInt(Long::intValue).boxed().collect(Collectors.toList());
               // }else if(obj[idEncryptHandler.reqDecryptIndex()] instanceof Long){
                    obj[idEncryptHandler.reqDecryptIndex()] = ids;
               // }
            }
        }
         return obj;
    }

    @Around("pointCut()")
    public Object pointCut(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        // 获取注解Action
        IdEncrypt idEncryptHandler = method.getAnnotation(IdEncrypt.class);
        Object[] obj = joinPoint.getArgs();
        if (idEncryptHandler.isObject()) {
            return joinPoint.proceed(obj);
        } else {
            if (idEncryptHandler.reqHandle() || (obj.length > 0 && Objects.isNull(obj[idEncryptHandler.reqDecryptIndex()]))) {
                //对请求参数解密处理
                obj =  dealRequestParamData(obj,idEncryptHandler);
            }
            Object returnObject = joinPoint.proceed(obj);
            String jsonString = new ObjectMapper().writeValueAsString(returnObject);
            //String jsonString = JSONObject.toJSONString(returnObject,SerializerFeature.WriteDateUseDateFormat);
            ReturnDataTypeEnum returnDataTypeEnum = idEncryptHandler.dataType();

            //判断返回数据类型
            if(ReturnDataTypeEnum.MAP.getType().equals(returnDataTypeEnum.getType())){
                if(!jsonString.contains("data")){
                    return returnObject;
                }
                Map contentJson = JsonPath.parse(jsonString).read("data");
                //如果返回数据为空,不做处理
                if(CollectionUtil.isEmpty(contentJson)){
                    return returnObject;
                }
            }else if(ReturnDataTypeEnum.LIST.getType().equals(returnDataTypeEnum.getType())){
                List contentJson = JsonPath.parse(jsonString).read("data");
                //如果返回数据为空,不做处理
                if(CollectionUtil.isEmpty(contentJson)){
                    return returnObject;
                }
            }else if(ReturnDataTypeEnum.UNENCRYPT.getType().equals(returnDataTypeEnum.getType())){
                //返回数据无需处理
                return returnObject;
            }else if(ReturnDataTypeEnum.DIRECT_LIST.getType().equals(returnDataTypeEnum.getType())){
                if("[]".equals(jsonString)){//数据为空,直接返回
                    return returnObject;
                }
            }

            //对返回数据的文章uuid加密处理
            if (idEncryptHandler.rewritePath().contains("*")) {
                List<Integer> srcIds = JsonPath.parse(jsonString).read(idEncryptHandler.sourcePath());
                LinkedList newIds = new LinkedList();
                for (Integer id : srcIds) {
                    //String nid = EncryptBodyMethod.DES.getISecurity().encrypt(String.valueOf(id), PASSWORD, config);
                    Long nid = DeAndEnUtil.encrypt(Long.valueOf(String.valueOf(id)));
                    newIds.add(nid);
                }
                String returnJsonString = jsonString;
                for (int i = 0; i < newIds.size(); i++) {
                    String accuteRewritePath = idEncryptHandler.rewritePath().replace("*", String.valueOf(i));
                    String rewritePath = accuteRewritePath + ".id";
                   // returnJsonString = JsonPath.parse(returnJsonString).set(rewritePath, 0).put(accuteRewritePath, idEncryptHandler.rewriteParam(), newIds.get(i)).jsonString();
                    returnJsonString = JsonPath.parse(returnJsonString).set(rewritePath, newIds.get(i)).jsonString();

                }
                returnObject = JSONObject.parseObject(returnJsonString, returnObject.getClass());
            } else {
                Integer id = (Integer) JsonPath.parse(jsonString).read(idEncryptHandler.sourcePath());
                //String returnJsonString = JsonPath.parse(jsonString).set(idEncryptHandler.rewritePath() + ".id", 0).put(idEncryptHandler.rewritePath(), idEncryptHandler.rewriteParam(), EncryptBodyMethod.DES.getISecurity().encrypt(String.valueOf(id), PASSWORD, config)).jsonString();
                String returnJsonString = JsonPath.parse(jsonString).set(idEncryptHandler.rewritePath() + ".id", DeAndEnUtil.encrypt(Long.valueOf(String.valueOf(id)))).jsonString();

                returnObject = JSONObject.parseObject(returnJsonString, returnObject.getClass());
            }
            return returnObject;
        }
    }


    private Map<String, Object> getFieldsNameValueMap(JoinPoint joinPoint) throws Exception {
        Object[] args = joinPoint.getArgs();
        String classType = joinPoint.getTarget().getClass().getName();
        Class<?> clazz = Class.forName(classType);
        String clazzName = clazz.getName();
        String methodName = joinPoint.getSignature().getName(); //获取方法名称
        Map<String, Object> map = new HashMap<String, Object>();
        ClassPool pool = ClassPool.getDefault();
        ClassClassPath classPath = new ClassClassPath(this.getClass());
        pool.insertClassPath(classPath);
        CtClass cc = pool.get(clazzName);
        CtMethod cm = cc.getDeclaredMethod(methodName);
        MethodInfo methodInfo = cm.getMethodInfo();
        CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
        LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
        if (attr == null) {
            throw new RuntimeException();
        }
        int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
        for (int i = 0; i < cm.getParameterTypes().length; i++) {
            map.put(attr.variableName(i + pos), args[i]);//paramNames即参数名
        }
        return map;
    }
}
 

三 使用方法。

  @GetMapping("/xxxxxx")
    @IdEncrypt(reqHandle = false, sourcePath = "$.data[*].id", rewritePath = "$.data[*]",type = BusinsTypeEnum.NEWS,dataType = ReturnDataTypeEnum.LIST)
    public AjaxResult xxxxxx( @RequestParam(value="ids") int[] ids)
    {
        if(ids != null && ids.length > 0 ){
            return AjaxResult.success(appDetailService.selectAppInfoByIds(ids));
        }else{
            return AjaxResult.success();
        }
    }

四,其他枚举类

public enum BusinsTypeEnum {
    NEWS_AAAA("newsaaa", "xxxx"),
    REPORT_AAAA("reportaaa", "xxxxx");

    @EnumValue
    @JsonValue
    private final String type;
    private final String message;

    public String getType() {
        return this.type;
    }

    public String getMessage() {
        return this.message;
    }

    private BusinsTypeEnum(String type, String message) {
        this.type = type;
        this.message = message;
    }
}

五,返回的数据类型

public enum ReturnDataTypeEnum {
    LIST("list", "返回的data组装数据类型是list"),
    MAP("map", "返回的data组装数据类型是map"),
    DIRECT_LIST("directList", "非data组装直接LIST返回数据类型"),
    UNENCRYPT("unencrypt", "返回的数据不需要加密");

    @EnumValue
    @JsonValue
    private final String type;
    private final String message;

    public String getType() {
        return this.type;
    }

    public String getMessage() {
        return this.message;
    }

    private ReturnDataTypeEnum(String type, String message) {
        this.type = type;
        this.message = message;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

JB091

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

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

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

打赏作者

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

抵扣说明:

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

余额充值