AOP实现接口加解密

接口加解密(主要实现分为 请求参数解密,返回参数加密 两个操作)
玩一下, 开搞,开搞!!!

实现思路

首先加解密用的就是各种加密算法进行处理的,之前我也发过多种加密方式的工具类(Java加密算法工具类(AES、DES、MD5、RSA)),其次就是用aop拦截处理,可以用自定义注解的形式定义是加密还是解密以及何种加解密方式,然后判断逻辑后在执行目标前后进行处理。aop拦截还有多种拦截方式我之前也有写过(JAVA三种拦截方式),可以参考下。

引入maven

<dependency>
   <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.75</version>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.6</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

核心代码

自定义注解

其实这两个注解是可以合成一个使用的,这边为了对比明显

/**
 * 加密类型枚举
 * (对应工具类中各个加解密类型)
 */
public enum EncryptType {
      AES,
      DES,
      MD5,
      RSA,
      NULL
}
import com.zhangximing.springboot_annotate.util.EncryptType;
import java.lang.annotation.*;

/**
 * @Author: zhangximing
 * @Email: 530659058@qq.com
 * @Date: 2024/4/6 10:28
 * @Description: 自定义加密
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface CustomEncryption {

    //加密类型
    EncryptType type() default EncryptType.NULL;

}
import com.zhangximing.springboot_annotate.util.EncryptType;
import java.lang.annotation.*;

/**
 * @Author: zhangximing
 * @Email: 530659058@qq.com
 * @Date: 2024/4/6 10:29
 * @Description: 自定义解密
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface CustomDecryption {

    //解密类型
    EncryptType type() default EncryptType.NULL;

}

AOP切面

注意算法部分参考之前(Java加密算法工具类(AES、DES、MD5、RSA)

import com.alibaba.fastjson.JSONObject;
import com.zhangximing.springboot_annotate.util.AESUtil;
import com.zhangximing.springboot_annotate.util.MD5Util;
import com.zhangximing.springboot_annotate.util.RSAUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Configuration;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * @Author: zhangximing
 * @Email: 530659058@qq.com
 * @Date: 2024/4/6 10:44
 * @Description: 加解密切面
 */
@Aspect
@Configuration
public class SecurityInterceptor {

    // 拦截用过加密注释的
    @Pointcut("@annotation(com.zhangximing.springboot_annotate.annotate.CustomEncryption)")
    public void encPointCut(){

    }

    // 拦截用过解密注释的
    @Pointcut("@annotation(com.zhangximing.springboot_annotate.annotate.CustomDecryption)")
    public void decPointCut(){

    }

    @Around("decPointCut() || encPointCut()")
    public Object AroundCustomDecryption(ProceedingJoinPoint point){

        // 前置逻辑
        Object result = null;

        //获得当前访问的class
        Class<?> className = point.getTarget().getClass();
        //获得访问的方法名
        String methodName = point.getSignature().getName();
        //得到方法的参数的类型
        Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();

//        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//        HttpServletRequest request = attributes.getRequest();
        //入参
        Object[] args = point.getArgs();
        JSONObject param = null;
        if (args != null && args.length > 0){
            param = JSONObject.parseObject(args[0].toString());
        }

        Method method = null;

        //解密
        try {
            // 得到访问的方法对象
            method = className.getMethod(methodName, argClass);

            // 判断是否存在@CustomDecryption
            if (method.isAnnotationPresent(CustomDecryption.class) && param != null){
                CustomDecryption customDecryption = method.getAnnotation(CustomDecryption.class);

                System.out.println("使用算法:" + customDecryption.type());

                // 解密数据
                String encryptData = param.getString("encryptData");
                if (null == encryptData || "".equals(encryptData)){
                    throw new RuntimeException("param error,encryptData is null");
                }

                String decryptData = "";
                System.out.println("解密前的数据:"+ encryptData);

                switch (customDecryption.type()){
                    case AES:
                        byte[] decrypted = AESUtil.decryptECB(AESUtil.key128, Base64.getDecoder().decode(encryptData));
                        decryptData = new String(decrypted, StandardCharsets.UTF_8);
                        break;
                    case DES:
						//jdk8才有sun.misc,这里不做展示
                        break;
                    case MD5:
                        //md5不支持解密
                        throw new RuntimeException("md5 decrypt error");
//                        break;
                    case RSA:
                        byte[] bytes = RSAUtil.decryptPrivateKey(Base64.getDecoder().decode(encryptData), RSAUtil.getRsaPrivateKey);
                        decryptData = new String(bytes);
                        break;
                    default:
                        break;
                }

                System.out.println("解密后的数据:"+ decryptData);
                param.put("decryptData", decryptData);
                //替换请求入参
                args[0] = param;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }

        // 执行目标方法
        try {
            result = point.proceed(args);
        } catch (Throwable e) {
            e.printStackTrace();
            return e.getMessage();
        }


        //加密
        try {
            // 判断是否存在@CustomEncryption
            if (method.isAnnotationPresent(CustomEncryption.class) && result != null){
                CustomEncryption customEncryption = method.getAnnotation(CustomEncryption.class);

                System.out.println("使用算法:" + customEncryption.type());
                String encryptData = "";
                System.out.println("加密前的数据:"+ result);
                String beforeResult = JSONObject.toJSONString(result);

                if (beforeResult.length() > 2){
                    beforeResult = beforeResult.substring(1, beforeResult.length() - 1);
                    beforeResult = beforeResult.replaceAll("\\\\", "");
                }
                System.out.println("加密前处理的数据:"+ beforeResult);

                switch (customEncryption.type()){
                    case AES:
                        byte[] decrypted = AESUtil.encryptECB(AESUtil.key128, beforeResult.getBytes(StandardCharsets.UTF_8));
                        encryptData = Base64.getEncoder().encodeToString(decrypted);
                        break;
                    case DES:
						//jdk8才有sun.misc,这里不做展示
                        break;
                    case MD5:
                        encryptData = MD5Util.getMd5(beforeResult);
                        break;
                    case RSA:
                        byte[] bytes = RSAUtil.encryptPublicKey(beforeResult.getBytes(), RSAUtil.getRsaPublicKey);
                        encryptData = Base64.getEncoder().encodeToString(bytes);
                        break;
                    default:
                        break;
                }

                JSONObject resultJson = new JSONObject();
                System.out.println("加密后的数据:"+ encryptData);
                resultJson.put("encryptData",encryptData);

                result = resultJson.toJSONString();
            }
        }catch (Exception e){
            e.printStackTrace();
            return e.getMessage();
        }


        return result;
    }
}

测试方法

import com.alibaba.fastjson.JSONObject;
import com.zhangximing.springboot_annotate.annotate.CustomDecryption;
import com.zhangximing.springboot_annotate.annotate.CustomEncryption;
import com.zhangximing.springboot_annotate.util.EncryptType;
import org.springframework.web.bind.annotation.*;

/**
 * 测试接口加解密
 */
@RestController
@RequestMapping("/security")
public class SecurityController {

    //解密测试
    @CustomDecryption(type = EncryptType.RSA)
    @RequestMapping("/decrypt")
    public String decrypt(@RequestBody JSONObject param) {

        return param.toJSONString();
    }

    //加密测试
    @CustomEncryption(type = EncryptType.RSA)
    @RequestMapping("/encrypt")
    public String encrypt(@RequestBody JSONObject param) {

        param.put("success","ok");
        return param.toJSONString();
    }
}

测试结果

接口加密(可以看到返回了加密后的字符串)

在这里插入图片描述

接口解密(可以看到返回了加解密后的字符串)

在这里插入图片描述

控制台打印(统一设置了RSA算法)

在这里插入图片描述

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

谦风(Java)

一起学习,一起进步(✪ω✪)

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

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

打赏作者

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

抵扣说明:

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

余额充值