接口加解密(主要实现分为 请求参数解密,返回参数加密 两个操作)
玩一下, 开搞,开搞!!!
目录
- 实现思路
- 引入maven
- 核心代码
- 自定义注解
- 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;//获得当前访问的classClass<?> 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);// 判断是否存在@CustomDecryptionif (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 {// 判断是否存在@CustomEncryptionif (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算法)