前言

最近项目组开始关注一些敏感数据的明文相关的事宜 , 其实这些东西也是都有非常成熟的解决方案。 既然最近着手去解决这些事情,那么也顺便给还未了解的大伙普及一下。

这个系列就暂短的分成三篇 :

第一篇    yml配置文件里敏感数据的加密
Springboot yml配置参数数据加密 (数据加密篇 一)_默默不代表沉默-CSDN博客

第二篇    传入数据敏感数据的加密存储

第三篇     使用mysql加解密函数轻松实现  

Springboot 使用mysql加密解密函数 (数据加密篇 三)_默默不代表沉默-CSDN博客

本篇是第二篇 ,基于第一篇已经整合了jasypt 的基础上 。

正文

内容:

1. 插入数据 自定义注解方式  对 指定接口方法 的 参数的指定字段进行 加密存储;

2.对数据内的加密数据,进行解密返回

先看看效果 :

数据存入数据库表内, 手机号phone和邮箱email 属于敏感数据,我们需要密文存储 :

查询解密返回:

1.  自定义注解 加密标识注解  NeedEncrypt.java :

import java.lang.annotation.*;/*** @Author JCccc* @Description 需加密* @Date 2021/7/23 11:55*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedEncrypt {}

2.自定义注解 需加密字段标识注解 EncryptField.java :

/*** @Author JCccc* @Description* @Date 2021/7/23 11:55*/
@Target({ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptField {String[] value() default "";
}

3.加密逻辑的aop处理器  EncryptAspect.java :

import com.elegant.dotest.aop.annotation.EncryptField;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.jasypt.encryption.StringEncryptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.lang.reflect.Field;
import java.util.Objects;/*** @Author JCccc* @Description* @Date 2021/9/14 8:55*/
@Slf4j
@Aspect
@Component
public class EncryptAspect {@Autowiredprivate StringEncryptor stringEncryptor;@Pointcut("@annotation(com.elegant.dotest.aop.annotation.NeedEncrypt)")public void pointCut() {}@Around("pointCut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {//加密encrypt(joinPoint);return joinPoint.proceed();}public void encrypt(ProceedingJoinPoint joinPoint)  {Object[] objects=null;try {objects = joinPoint.getArgs();if (objects.length != 0) {for (int i = 0; i < objects.length; i++) {//抛砖引玉 ,可自行扩展其他类型字段的判断if (objects[i] instanceof String) {objects[i] = encryptValue(objects[i]);} else {encryptObject(objects[i]);}}}} catch (Exception e) {e.printStackTrace();}}/*** 加密对象* @param obj* @throws IllegalAccessException*/private void encryptObject(Object obj) throws IllegalAccessException {if (Objects.isNull(obj)) {log.info("当前需要加密的object为null");return;}Field[] fields = obj.getClass().getDeclaredFields();for (Field field : fields) {boolean containEncryptField = field.isAnnotationPresent(EncryptField.class);if (containEncryptField) {//获取访问权field.setAccessible(true);String value = stringEncryptor.encrypt(String.valueOf(field.get(obj)));field.set(obj, value);}}}/*** 加密单个值* @param realValue* @return*/public String encryptValue(Object realValue) {try {realValue = stringEncryptor.encrypt(String.valueOf(realValue));} catch (Exception e) {log.info("加密异常={}",e.getMessage());}return String.valueOf(realValue);}}

4. 插入user表 使用的 User.java :

import com.elegant.dotest.aop.annotation.EncryptField;
import lombok.Data;
import lombok.experimental.Accessors;/*** @Author JCccc* @Description* @Date 2021/9/14 8:55*/
@Data
@Accessors(chain = true)
public class User {private Integer id;private String name;@EncryptFieldprivate String phone;@EncryptFieldprivate String email;private Integer age;}

可以看到,手机号phone 和 邮箱 email 两个字段,我们做了注解 @EncryptField 标识:

ok,我们写个测试接口,使用 @NeedEncrypt 注解标识这个接口需要进行加密拦截 :

使用postman调用一下测试接口:

可以看下数据库,数据已经加密存储成功:

接下来是查询解密环节:

解密这里其实有些小讲究。 因为查询出来的数据有可能是单个实体,也可能是List (其实甚至是Map或者Set,又或者是 分页数据类)

所以本文将会以 最常用的 单个实体 、 List<实体> 为例子,去做解密。

1.解密自定义注解 NeedDecrypt.java :

/*** @Author JCccc* @Description 需解密* @Date 2021/7/23 11:55*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedDecrypt {}

2. 解密逻辑的aop处理器  DecryptAspect.java :

import com.elegant.dotest.aop.annotation.EncryptField;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.jasypt.encryption.StringEncryptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;/*** @Author JCccc* @Description* @Date 2021/9/14 8:55*/
@Slf4j
@Aspect
@Component
public class DecryptAspect {@Autowiredprivate StringEncryptor stringEncryptor;@Pointcut("@annotation(com.elegant.dotest.aop.annotation.NeedDecrypt)")public void pointCut() {}@Around("pointCut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {//解密Object result = decrypt(joinPoint);return result;}public Object decrypt(ProceedingJoinPoint joinPoint) {Object result = null;try {Object obj = joinPoint.proceed();if (obj != null) {//抛砖引玉 ,可自行扩展其他类型字段的判断if (obj instanceof String) {decryptValue(obj);} else {result = decryptData(obj);}}} catch (Throwable e) {e.printStackTrace();}return result;}private Object decryptData(Object obj) throws IllegalAccessException {if (Objects.isNull(obj)) {return null;}if (obj instanceof ArrayList) {decryptList(obj);} else {decryptObj(obj);}return obj;}/*** 针对单个实体类进行 解密* @param obj* @throws IllegalAccessException*/private void decryptObj(Object obj) throws IllegalAccessException {Field[] fields = obj.getClass().getDeclaredFields();for (Field field : fields) {boolean hasSecureField = field.isAnnotationPresent(EncryptField.class);if (hasSecureField) {field.setAccessible(true);String realValue = (String) field.get(obj);String value = stringEncryptor.decrypt(realValue);field.set(obj, value);}}}/*** 针对list<实体来> 进行反射、解密* @param obj* @throws IllegalAccessException*/private void decryptList(Object obj) throws IllegalAccessException {List<Object> result = new ArrayList<>();if (obj instanceof ArrayList) {for (Object o : (List<?>) obj) {result.add(o);}}for (Object object : result) {decryptObj(object);}}public String decryptValue(Object realValue) {try {realValue = stringEncryptor.encrypt(String.valueOf(realValue));} catch (Exception e) {log.info("解密异常={}", e.getMessage());}return String.valueOf(realValue);}}

然后我们对一个查询方法进行测试 :

我们先试一下查询单条数据的:

使用@NeedDecrypt注解标记这个接口需要数据解密:

调用接口看看结果:

然后是多条数据List<User> 返回的接口:

调用接口测试看看结果:

Springboot AOP实现指定敏感字段数据加密 (数据加密篇 二)相关推荐

  1. java使用mybatis拦截器对数据库敏感字段进行加密存储并解密

    记录业务中遇到的使用场景:灵活对数据库敏感字段进行加密和解密 文章目录 前言 一.创建数据库表和实体类 二.Mapper.Service.Controller等 三.自定义注解 四.加密工具类 五.参 ...

  2. Springboot项目如何设计接口中敏感字段模糊查询?

    目录 前言 场景分析 实现方案 环境配置 依赖配置 代码实现 总结 前言 在<Springboot项目如何设计接口中敏感字段的加密.解密>和<Springboot项目如何设计接口中敏 ...

  3. springboot实现敏感字段加密存储,解密显示

    springboot实现敏感字段加密存储,解密显示,通过mybatis,自定义注解+AOP切面,Base64加解密方式实现功能. 1.代码实现: 创建springboot项目 添加依赖 <dep ...

  4. springBoot Aop打印日志

    springBoot Aop打印日志 1.类上加@Aspect,@Component注解 2.@Pointcut()定义一个切点,里面填写路径,一般是所有controller中的所有方法,所有的参数 ...

  5. SpringBoot+AOP实现多数据源动态切换

    SpringBoot+AOP实现多数据源动态切换 背景 设计总体思路 步骤 背景 系统后端需要访问多个数据库,现有的数据库连接配置写入配置文件中.后端需要从一个数据库的配置表里动态的读取其它mysql ...

  6. Spring-Boot + AOP实现多数据源动态切换

    2019独角兽企业重金招聘Python工程师标准>>> 最近在做保证金余额查询优化,在项目启动时候需要把余额全量加载到本地缓存,因为需要全量查询所有骑手的保证金余额,为了不影响主数据 ...

  7. SpringBoot+AOP构建多数据源的切换实践

    针对微服务架构中常用的设计模块,通常我们都会需要使用到druid作为我们的数据连接池,当架构发生扩展的时候 ,通常面对的数据存储服务器也会渐渐增加,从原本的单库架构逐渐扩展为复杂的多库架构. 当在业务 ...

  8. SpringBoot+AOP(@Around)

    SpringBoot+AOP(@Around) 虽然SpringBoot很方便,可以使我们不太懂原理的情况下都可以轻松的写出一个CRUD的项目,但是SpringBoot的控制反转和依赖注入我们时时刻刻 ...

  9. 敏感字段加密,叶俊峰

    /** 标题:敏感字段加密 | 时间限制:1秒 | 内存限制:262144K | 语言限制:不限 [敏感字段加密]给定一个由多个命令字组成的命令字符串: 1.字符串长度小于等于127字节,只包含大小写 ...

最新文章

  1. 2018目标,提高免疫力,身体工作双丰收
  2. JAVA SE学习day_15:thread线程池
  3. make的常见错误信息
  4. Django create_user with is_active=False
  5. (六)nodejs循序渐进-数据流和文件操作(基础篇)
  6. 枚举类型用法_Mybatis-plus常见用法总结三
  7. Oracle APEX 系列文章1:Oracle APEX, 让你秒变全栈开发的黑科技
  8. 主板检测卡c5_检测升级 | 华北工控推出机器视觉检测系统计算机产品方案
  9. jcodec_java-jcodec-有人看过该库的文档吗?
  10. 拓端tecdat|python爬虫进行Web抓取LDA主题语义数据分析报告
  11. native方法在java中介绍及使用图解
  12. CentOS 配置DHCPv6
  13. oracle财务数据权限思考
  14. 深圳大学毕业答辩PPT模板
  15. Android 图片压缩也即生成缩略图方法
  16. 致知在格物,物格而后知至,知至而后意诚,意诚而后心正,心正而后身修,身修而后家齐,家齐而后...
  17. sql条件查询表数据条数
  18. C51单片机实验系列:循环左移点亮流水灯_crol_
  19. Mysql工作原理——redo日志文件和恢复操作
  20. 基于Android的手机安全卫士的开发

热门文章

  1. 网络安全入门(一)IP欺骗
  2. JAVA实现二维码生成加背景图
  3. 验证码:请证明你是人类
  4. alma linux 8.6显示桌面图标
  5. muduo源码分析之TcpServer模块
  6. tinyxml2使用
  7. 人工智能助力金融贷款提高销售业绩
  8. Unity3D网络游戏0.1
  9. sequence机制
  10. ViewPage 实现卡片效果