AOP切面实现加密解密遇到的问题

一、需求

被@EncryptMethod标注的方法为切入点,对被@EncryptField注解标注的参数进行加密解密。

二、问题列表

(基本等于初次使用切面,遇到的问题有些许智障,不许嘲笑,嘲笑我就打你👊)

问题一:

能进入增强方法,但无法进入目标业务方法

解决:

没有调用 point.proceed(),该方法旨在调用目标方法,并获取其返回值。(没有调用该方法又怎么会进入业务呢😓,我是白痴)

问题二:

获取参数上的注解(刚开始一直着眼于单个参数上的注解,比如其中一个参数@EncryptField String name,一直不知道该怎么获取,后来看到可以一次获取方法所有参数的注解,获取方法如下)

解决:
//方法签名。方法签名是方法的形式定义,它提供了对该功能的高级描述。
MethodSignature methodSig = (MethodSignature) joinPoint.getSignature();
//获取方法中参数上的注解
Annotation[][] annotations = methodSig.getMethod().getParameterAnnotations();

annotations 是一个二维数组,第一维是参数序号,第二维是其对应的注解。

问题三:

切面加密成功,但进入目标方法的参数依然是未加密的

解决:

没有将加密后的参数传入point.proceed()🤦‍

Object result = joinPoint.proceed(joinPoint.getArgs());

综上,所有的问题都很基础,就是因为我对基础知识不熟造成的,以后我一定先了解好基础知识再上手做(ง •_•)ง。最后,附上代码。第一次可能做的不好,有什么建议都可以说哦,成长靠你了🤝。

@Documented
@Target({ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptField {

    String[] value() default "";
}
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptMethod {

    String type() default "encrypt";
}

@Slf4j
@Aspect
@Component
public class EncryptHandler {

    @Resource
    private StringEncryptor stringEncryptor;

    @Pointcut("@annotation(com.example.demo.utils.EncryptMethod)")
    public void pointCut(){
    }

    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        /**
         * 加密
         */
        encrypt(joinPoint);

        Object result = joinPoint.proceed(joinPoint.getArgs());

        /**
         * 解密
         */
        Object decrypt = decrypt(joinPoint);
        return decrypt;
    }



    public void encrypt(ProceedingJoinPoint joinPoint){
        try {
            //方法签名。方法签名是方法的形式定义,它提供了对该功能的高级描述。
            MethodSignature methodSig = (MethodSignature) joinPoint.getSignature();
            //获取方法中参数上的注解
            Annotation[][] annotations = methodSig.getMethod().getParameterAnnotations();
            Object[] args = joinPoint.getArgs();
            for(int i = 0; i < args.length; i++){
                for(Annotation annotation:annotations[i]){
                    if (EncryptField.class.isInstance(annotation)) {
                        args[i] = encryptValue(args[i]);
                        break;
                    }else if(RequestBody.class.isInstance(annotation)){
                        handler(args[i],"encrypt");
                        break;
                    }
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public Object decrypt(ProceedingJoinPoint joinPoint){
        Object result=null;
        try {
            MethodSignature methodSig = (MethodSignature) joinPoint.getSignature();
            Annotation[][] annotations = methodSig.getMethod().getParameterAnnotations();
            Object[] args = joinPoint.getArgs();
            for(int i = 0; i < args.length; i++){
                for(Annotation annotation:annotations[i]){
                    if (EncryptField.class.isInstance(annotation)) {
                        args[i] = decryptValue(args[i]);
                        break;
                    }else if(RequestBody.class.isInstance(annotation)){
                        result=handler(args[i],"decrypt");
                        break;
                    }
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return result;
    }

    public Object encryptValue(Object realValue){
        String value=null;
        try {
            value=stringEncryptor.encrypt(String.valueOf(realValue));
        }catch (Exception e){
            return value;
        }

        return value;

    }

    public String decryptValue(Object realValue) {
        String value = String.valueOf(realValue);
        try {
            value = stringEncryptor.decrypt(value);
        } catch (Exception ex) {
            return value;
        }
        return value;
    }

    public Object handler(Object obj,String type) throws IllegalAccessException {
        if(obj==null){
            return null;
        }
        Field[] declaredFields = obj.getClass().getDeclaredFields();
        for(Field field:declaredFields){
            boolean hasSecureField  = field.isAnnotationPresent(EncryptField.class);
            if(hasSecureField ){
                field.setAccessible(true);
                String realValue = (String)field.get(obj);
                String value;
                if("encrypt".equals(type)){
                    value=stringEncryptor.encrypt(realValue);
                }else{
                    value=stringEncryptor.decrypt(realValue);
                }
                field.set(obj,value);
            }
        }
        return obj;
    }
}
@RestController
@RequestMapping("/encrypt")
public class EncryptController {

    @Resource
    private StringEncryptor stringEncryptor;
    
    @EncryptMethod
    @RequestMapping("/test")
    //这里之所以没把name放进user里,是想试一下这种方式传入的参数如何处理
    public Object test(@RequestBody User user, @EncryptField @RequestParam String name){

        return insertUser(user,name);
    }

    private UserVo insertUser(User user,String name){
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user,userVo);
        userVo.setName(name);
        System.out.println("加密后的数据:user"+ JSON.toJSONString(userVo));
        return userVo;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值