Springboot+AOP+注解实现字段AES+Base64加解密

AOP实现AES+BASE64加解密

场景如下:
需要对数据库存储的字段,进行加解密的处理。如果都直接写代码的话,那么代码回冗余很多,所以使用AOP+注解去实现。让代码简洁,方便

具体实现如下:

1、依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.20</version><scope>compile</scope></dependency>
2、相关注解
package com.walker.aop.fieldAop.annotations;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* author:walker
* time: 2023/12/8
* description:  支持属性加密注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SupportFieldEncrypt {
}
package com.walker.aop.fieldAop.annotations;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/**
* author:walker
* time: 2023/12/8
* description: 支持属性解密注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SupportFieldDecrypt {
}
package com.walker.aop.fieldAop.annotations;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/**
* author:walker
* time: 2023/12/8
* description: 属性加密
*/
@Target(value = ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldEncrypt {/*** 具体参数查看FieldEncryptTypeEnums枚举* 默认使用AES+BASE64加密*/int type() default 1;
}
package com.walker.aop.fieldAop.annotations;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* author:walker
* time: 2023/12/8
* description:  属性解密
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldDecrypt {int type() default 1;
}
3、枚举

目前只整合了AES加密的,后续如果需要,可以自己整合

package com.walker.aop.fieldAop.enums;public enum FieldEncryptTypeEnums {AES_BASE64(1,"AES+BASE64");private Integer type;private String description;FieldEncryptTypeEnums(Integer type, String description) {this.type = type;this.description = description;}public Integer getType() {return type;}public void setType(Integer type) {this.type = type;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}
}
4、AES加解密工具类
package com.walker.aop.fieldAop;import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;import java.nio.charset.StandardCharsets;
/**
* author:walker
* time: 2023/12/7
* description:  AES加解密工具
*/
public class MyAesUtils {//    密钥,可以自己修改,当然这里可以不在这里写死,但是这里为了方便,就直接写死了private final static String AES_KEY="qu6ciLzMME7slNxj";private static final AES aes = SecureUtil.aes(AES_KEY.getBytes(StandardCharsets.UTF_8));public static String encrypt(String data){return Base64.encode(aes.encrypt(data));}public static String decrypt(String data){return aes.decryptStr(Base64.decode(data));}public static void main(String[] args) {String hello = encrypt("hello");System.out.println(hello);String decrypt = decrypt(hello);System.out.println(decrypt);}
}
5、切面类
package com.walker.aop.fieldAop.aspect;import cn.hutool.core.util.ReflectUtil;
import com.walker.aop.fieldAop.enums.FieldEncryptTypeEnums;
import com.walker.aop.fieldAop.MyAesUtils;
import com.walker.aop.fieldAop.annotations.FieldDecrypt;
import com.walker.aop.fieldAop.annotations.FieldEncrypt;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;import java.lang.annotation.Annotation;
import java.lang.reflect.Field;@Slf4j
//1、使用切面注解
@Aspect
@Component
public class FieldAopAspect {//    2、这里的引用路径需要根据自己项目的包去调整@Pointcut("@annotation(com.walker.aop.fieldAop.annotations.SupportFieldEncrypt)")public void supportFieldEncrypt() {};@Pointcut("@annotation(com.walker.aop.fieldAop.annotations.SupportFieldDecrypt)")public void supportFieldDecrypt() {};/*** author:walker* time: 2023/12/8* description:  前置通知 加密处理*/
//    3、Before代表前置通知@Before("supportFieldEncrypt()")public void fieldEncryptProcessor(JoinPoint joinPoint){//获取参数Object[] args = joinPoint.getArgs();if(args==null||args.length==0){return;}for (Object arg : args) {Class<?> aClass = arg.getClass();
//            获取属性Field[] fields = aClass.getDeclaredFields();for (Field field : fields) {
//                获取注解Annotation[] annotations = field.getAnnotations();for (Annotation annotation : annotations) {
//                    判断是否有FieldEncrypt注解if(annotation.annotationType().equals(FieldEncrypt.class)){FieldEncrypt fieldEncrypt= (FieldEncrypt) annotation;int type = fieldEncrypt.type();if(type== FieldEncryptTypeEnums.AES_BASE64.getType()){
//                            如果有注解,则进行加密处理,并使用反射去设置值Object fieldValue = ReflectUtil.getFieldValue(arg, field);if(fieldValue==null) return;String encrypt = MyAesUtils.encrypt(String.valueOf(fieldValue));System.out.println("加密后结果:"+encrypt);ReflectUtil.setFieldValue(arg,field,encrypt);}}}}}}/*** 解密注解*/
//    返回后通知@AfterReturning(value = "supportFieldDecrypt()",returning = "arg")public void fieldDecryptProcess(JoinPoint joinPoint, Object arg){if(arg==null) return;
//        arg:代表的是返回的结果Class<?> aClass = arg.getClass();
//        获取属性Field[] fields = aClass.getDeclaredFields();for (Field field : fields) {Annotation[] annotations = field.getAnnotations();for (Annotation annotation : annotations) {
//                判断属性是否有FieldDecrypt注解if(annotation.annotationType().equals(FieldDecrypt.class)){FieldDecrypt fieldDecrypt= (FieldDecrypt) annotation;int type = fieldDecrypt.type();
//                    如果存在注解,则进行解密并且重新设置回对象中if(type==FieldEncryptTypeEnums.AES_BASE64.getType()){Object fieldValue = ReflectUtil.getFieldValue(arg, field);System.out.println("解密前结果:"+fieldValue);if(fieldValue==null) return;String decrypt = MyAesUtils.decrypt(String.valueOf(fieldValue));System.out.println("解密后结果:"+decrypt);ReflectUtil.setFieldValue(arg,field,decrypt);}}}}}
}
6、测试
  • 测试实体类
package com.walker.aop.fieldAop;import com.walker.aop.fieldAop.annotations.FieldDecrypt;
import com.walker.aop.fieldAop.annotations.FieldEncrypt;
import lombok.Data;@Data
public class FieldAopDemo {@FieldEncrypt@FieldDecryptprivate String name;
}
  • controller
package com.walker.aop.fieldAop;import com.walker.aop.fieldAop.annotations.SupportFieldDecrypt;
import com.walker.aop.fieldAop.annotations.SupportFieldEncrypt;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/fieldAOP")
public class FieldAOPController {@SupportFieldEncrypt@GetMapping("/encrypt")public void encrypt(FieldAopDemo demo){System.out.println(demo);return;}@SupportFieldDecrypt@GetMapping("/decrypt")public FieldAopDemo decrypt(FieldAopDemo demo){System.out.println(demo);String name = demo.getName();String encrypt = MyAesUtils.encrypt(name);System.out.println(encrypt);demo.setName(encrypt);return demo;}
}

之后使用postman调用结果测试:
加密测试:
http://localhost:8080/fieldAOP/encrypt?name=hello
image.png

解密测试:
http://localhost:8080/fieldAOP/decrypt?name=hello
image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/258758.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

混合预编码(Hybrid Precoding)的全连接结构与子连接结构

A Survey on Hybrid Beamforming Techniques in 5G: Architecture and System Model Perspectives 全连接结构的混合预编码 子连接结构的混合预编码 Alternating Minimization Algorithms for HybridPrecoding in Millimeter Wave MIMO Systems

最新Redis7 的十大数据类型(最全指令)

Redis 是一种高性能的键值存储系统&#xff0c;支持多种数据类型。以下是 Redis 的十大主要数据类型&#xff1a; 字符串 (String): 最简单的数据类型&#xff0c;可以包含任意数据&#xff0c;如文本、二进制数据等。 列表 (List): 有序的字符串元素集合&#xff0c;支持从两…

vscode 如何将正则匹配到的字符前批量加字符

最近想用vscode将正则匹配到的东西签名批量https&#xff0c;替换时可以用$1来替换正则匹配到的字符串&#xff0c;如下所示

MySQL中是如何insert数据的

正常insert数据&#xff0c;MySQL并不会显式加锁&#xff0c;而是通过聚簇索引的trx_id索引作为隐式锁来保护记录的。比如两个事务对一个非唯一的索引情况添加&#xff0c;会造成幻读 但在某些特殊情况下&#xff0c;隐式锁会转变为显式锁&#xff1a; 记录之间有间隙锁inser…

扩展学习|商业智能和分析:从大数据到大影响

文献来源&#xff1a;Chen H, Chiang R H L, Storey V C. Business intelligence and analytics: From big data to big impact[J]. MIS quarterly, 2012: 1165-1188. 下载链接&#xff1a;https://pan.baidu.com/s/1JoHcTbwdc1TPGnwXsL4kIA 提取码&#xff1a;a8uy 在不同的组…

WeiPHP 微信开发平台 SQL注入漏洞复现

0x01 产品简介 weiphp 是一个开源,高效,简洁的微信开发平台,基于 oneThink 内容管理框架实现。 0x02 漏洞概述 weiphp 微信开发平台 _send_by_group、 wp_where、 get_package_template等接口处存在 SQL 注入漏洞,攻击者利用此漏洞可获取数据库中的信息(例如,管理员后台…

六款好用的设备管理系统推荐

阅读本文你将了解&#xff1a;一、六款好用的设备管理系统&#xff1b;二、企业为什么要做设备管理&#xff1b;三、企业怎样选择适合自己的设备管理系统。 制造企业生产过程中对机器设备的依赖程度非常高&#xff0c;因而一系列设备巡检、维修、保养的管理需求也应运而生。设…

C++核心编程——继承与派生

C核心编程——继承与派生 继承与派生的概念继承派生的概念派生类的声明方式派生类的构成 派生类成员的访问属性公用继承私有继承保护继承 派生类的构造函数与析构函数简单派生类构造函数有子对象的派生类的构造函数多层派生时的构造函数 多重继承声明多重继承的方法多重继承引起…

11K+ Star!图解计算机网络、操作系统、计算机组成、数据库!

大家好&#xff0c;我是 Java陈序员。 俗话说得好&#xff0c;面试造火箭&#xff0c;入职拧螺丝。我们在工作中&#xff0c;其实很少用到一些计算机底层知识&#xff0c;往往只要编码完事。但是&#xff0c;知其然还要知其所以然&#xff0c;我们不仅要做一个合格的“CV 工程…

第21章总结 网络通信

21.1 网络程序设计基础 网络程序设计编写的是与其他计算机进行通信的程序。Java已经将网络程序所需要的元素封装成不同的类&#xff0c;用户只要创建这些类的对象&#xff0c;使用相应的方法&#xff0c;即使不具备有关的网络知识&#xff0c;也可以编写出高质量的网络通信程序…

excel做预测的方法集合

一. LINEST函数 首先&#xff0c;一元线性回归的方程&#xff1a; y a bx 相应的&#xff0c;多元线性回归方程式&#xff1a; y a b1x1 b2x2 … bnxn 这里&#xff1a; y - 因变量即预测值x - 自变量a - 截距b - 斜率 LINEST的可以返回回归方程的 截距(a) 和 斜…

DouyinAPI接口开发系列丨商品详情数据丨视频详情数据

电商API就是各大电商平台提供给开发者访问平台数据的接口。目前&#xff0c;主流电商平台如淘宝、天猫、京东、苏宁等都有自己的API。 二、电商API的应用价值 1.直接对接原始数据源&#xff0c;数据提取更加准确和完整。 2.查询速度更快&#xff0c;可以快速响应用户请求实现…