springboot项目通过自定义注解+aop实现对入参加解密

1.创建自定义注解:

java 复制代码
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptDecrypt {
}

2.创建加解密工具类:

java 复制代码
public class EncryptionUtils {
    // 加密方法
    public static String encrypt(String data) {
        // 实现加密逻辑
        // ...
        return encryptedData;
    }

    // 解密方法
    public static String decrypt(String encryptedData) {
        // 实现解密逻辑
        // ...
        return decryptedData;
    }
}

3.创建切面类:

java 复制代码
@Aspect
@Component
public class EncryptionAspect {

    @Around("execution(* com.example.*.*(..)) && (@annotation(com.example.EncryptDecrypt) || @args(com.example.EncryptDecrypt))")
    public Object encryptDecryptMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取方法参数
        Object[] args = joinPoint.getArgs();

        // 遍历参数,对带有 EncryptDecrypt 注解的参数进行加解密操作
        for (int i = 0; i < args.length; i++) {
            Object arg = args[i];
            if (arg != null) {
                if (arg instanceof String) {
                    if (arg.getClass().isAnnotationPresent(EncryptDecrypt.class)) {
                        String encryptedData = (String) arg;
                        String decryptedData = EncryptionUtils.decrypt(encryptedData);
                        args[i] = decryptedData;
                    }
                } else {
                    Field[] fields = arg.getClass().getDeclaredFields();
                    for (Field field : fields) {
                        if (field.isAnnotationPresent(EncryptDecrypt.class)) {
                            field.setAccessible(true);
                            Object fieldValue = field.get(arg);
                            if (fieldValue instanceof String) {
                                String encryptedData = (String) fieldValue;
                                String decryptedData = EncryptionUtils.decrypt(encryptedData);
                                field.set(arg, decryptedData);
                            }
                        }
                    }
                }
            }
        }

        // 执行原方法
        Object result = joinPoint.proceed(args);

        // 对返回值进行加密操作(可根据需求进行操作)

        return result;
    }
}

4.参数解释

java 复制代码
@Target({ElementType.FIELD, ElementType.PARAMETER}) 是一个注解的元注解,用于指定注解可以应用的目标元素类型。在这个例子中,@Target 注解表明注解 EncryptDecrypt 可以应用于字段(Field)和参数(Parameter)上。

ElementType.FIELD 表示注解可以应用于字段上,即类的成员变量。
ElementType.PARAMETER 表示注解可以应用于方法的参数上。
通过指定这些目标元素类型,你可以限制注解的使用范围,确保它只能应用在指定的地方。在这个场景中,EncryptDecrypt 注解旨在用于标记需要进行加解密操作的字段和方法参数。
java 复制代码
1.execution(* com.example.*.*(..)):表示匹配 com.example 包及其子包下的所有类的所有方法。

		execution() 是切点函数,用于匹配方法执行的连接点。
		* 表示匹配任意返回类型的方法。
		com.example.* 表示匹配 com.example 包下的任意类。
		*.*(..) 表示匹配任意方法名和参数的方法。
		
2.(@annotation(com.example.EncryptDecrypt) || @args(com.example.EncryptDecrypt)):表示匹配带有 EncryptDecrypt 注解的方法或参数。

		@annotation(com.example.EncryptDecrypt) 匹配带有 EncryptDecrypt 注解的方法。
		@args(com.example.EncryptDecrypt) 匹配带有 EncryptDecrypt 注解的参数。

-----------------------------------------分割线-------------------------------------------------------------------------------------------

对出参进行解密

注解类

java 复制代码
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Decrypt {
    String value() default "";
}
java 复制代码
mport org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Collection;

@Aspect
@Component
public class DecryptionAspect {

    @Around("execution(* com.example.*.*(..))")
    public Object decryptMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        // 执行原方法并获取返回值
        Object result = joinPoint.proceed();

        // 对带有 @Decrypt 注解的字段进行解密操作
        if (result != null) {
            if(result instanceof GatewayResp){
            //GatewayResp 为统一定义的出参 包括code,msg,data
                GatewayResp r = (GatewayResp) result;
                Object data = r.getData();
                if(data instanceof Collection<?>) {
                    //集合
                    data = decryptCollectionFields((Collection<?>)data);
                }else{
                    //单对象
                    data = decryptObjectFields(data);
                }
                r.setData(data);
            }

        }

        return result;
    }

    private Collection<?> decryptCollectionFields(Collection<?> collection) throws IllegalAccessException {
        for (Object object : collection) {
            decryptObjectFields(object);
        }
        return collection;
    }
    private Object decryptObjectFields(Object object) throws IllegalAccessException {
        Field[] fields = object.getClass().getDeclaredFields();

        for (Field field : fields) {
            // 如果字段带有 @Decrypt 注解,则对其进行解密操作
            if (field.isAnnotationPresent(Decrypt.class)) {
                field.setAccessible(true);
                Object fieldValue = field.get(object);

                if (fieldValue instanceof String) {
                    String decryptedValue = EncryptionUtils.decrypt((String) fieldValue);
                    field.set(object, decryptedValue);
                }
            } else {
                // 如果字段不带有 @Decrypt 注解,则递归调用 decryptObjectFields() 方法
                field.setAccessible(true);
                Object fieldValue = field.get(object);

                if (fieldValue != null) {
                    if (fieldValue instanceof Collection<?>) {
                        decryptCollectionFields((Collection<?>) fieldValue);
                    } else if(isCustomObject(fieldValue)){
                        decryptObjectFields(fieldValue);
                    }
                }
            }
        }
        return object;
    }

    /**
     * 判断一个对象不是八大基本数据类型和String类型
     */
    private boolean isCustomObject(Object object) {
        Class<?> objectType = object.getClass();

        // 判断是否为八大基本数据类型
        if (objectType.isPrimitive()) {
            return false;
        }

        // 判断是否为String类型
        if (objectType.equals(String.class)) {
            return false;
        }

        return true;
    }
}
相关推荐
腥臭腐朽的日子熠熠生辉27 分钟前
解决maven失效问题(现象:maven中只有jdk的工具包,没有springboot的包)
java·spring boot·maven
ejinxian29 分钟前
Spring AI Alibaba 快速开发生成式 Java AI 应用
java·人工智能·spring
杉之34 分钟前
SpringBlade 数据库字段的自动填充
java·笔记·学习·spring·tomcat
圈圈编码1 小时前
Spring Task 定时任务
java·前端·spring
俏布斯1 小时前
算法日常记录
java·算法·leetcode
27669582921 小时前
美团民宿 mtgsig 小程序 mtgsig1.2 分析
java·python·小程序·美团·mtgsig·mtgsig1.2·美团民宿
爱的叹息1 小时前
Java 连接 Redis 的驱动(Jedis、Lettuce、Redisson、Spring Data Redis)分类及对比
java·redis·spring
程序猿chen1 小时前
《JVM考古现场(十五):熵火燎原——从量子递归到热寂晶壁的代码涅槃》
java·jvm·git·后端·java-ee·区块链·量子计算
松韬2 小时前
Spring + Redisson:从 0 到 1 搭建高可用分布式缓存系统
java·redis·分布式·spring·缓存
绝顶少年2 小时前
Spring Boot 注解:深度解析与应用场景
java·spring boot·后端