SpringBoot配置文件、隐私数据脱敏的完美实践(2)

预先生成的加密值,可以通过代码内调用API生成

@Autowired

private StringEncryptor stringEncryptor;

public void encrypt(String content) {

String encryptStr = stringEncryptor.encrypt(content);

System.out.println(“加密后的内容:” + encryptStr);

}

或者通过如下Java命令生成,几个参数D:\maven_lib\org\jasypt\jasypt\1.9.3\jasypt-1.9.3.jar为jasypt核心jar包,input待加密文本,password秘钥,algorithm为使用的加密算法。

java -cp D:\maven_lib\org\jasypt\jasypt\1.9.3\jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input=“root” password=xiaofu algorithm=PBEWithMD5AndDES

SpringBoot配置文件、隐私数据脱敏的最佳实践

一顿操作后如果还能正常启动,说明配置文件脱敏就没问题了。

敏感字段脱敏

======

生产环境用户的隐私数据,比如手机号、身份证或者一些账号配置等信息,入库时都要进行不落地脱敏,也就是在进入我们系统时就要实时的脱敏处理。

用户数据进入系统,脱敏处理后持久化到数据库,用户查询数据时还要进行反向解密。这种场景一般需要全局处理,那么用AOP切面来实现再适合不过了。

SpringBoot配置文件、隐私数据脱敏的最佳实践

首先自定义两个注解@EncryptField、@EncryptMethod分别用在字段属性和方法上,实现思路很简单,只要方法上应用到@EncryptMethod注解,则检查入参字段是否标注@EncryptField注解,有则将对应字段内容加密。

@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;

}

切面的实现也比较简单,对入参加密,返回结果解密。为了方便阅读这里就只贴出部分代码,完整案例Github地址:

https://github.com/chengxy-nds/Springboot-Notebook/tree/master/springboot-jasypt

@Slf4j

@Aspect

@Component

public class EncryptHandler {

@Autowired

private StringEncryptor stringEncryptor;

@Pointcut(“@annotation(com.xiaofu.annotation.EncryptMethod)”)

public void pointCut() {

}

@Around(“pointCut()”)

public Object around(ProceedingJoinPoint joinPoint) {

/**

  • 加密

*/

encrypt(joinPoint);

/**

  • 解密

*/

Object decrypt = decrypt(joinPoint);

return decrypt;

}

public void encrypt(ProceedingJoinPoint joinPoint) {

try {

Object[] objects = joinPoint.getArgs();

if (objects.length != 0) {

for (Object o : objects) {

if (o instanceof String) {

encryptValue(o);

} else {

handler(o, ENCRYPT);

}

//TODO 其余类型自己看实际情况加

}

}

} catch (IllegalAccessException e) {

e.printStackTrace();

}

}

public Object decrypt(ProceedingJoinPoint joinPoint) {

Object result = null;

try {

Object obj = joinPoint.proceed();

if (obj != null) {

if (obj instanceof String) {

decryptValue(obj);

} else {

result = handler(obj, DECRYPT);

}

//TODO 其余类型自己看实际情况加

}

} catch (Throwable e) {

e.printStackTrace();

}

return result;

}

。。。

}

紧接着测试一下切面注解的效果,我们对字段mobile、address加上注解@EncryptField做脱敏处理。

@EncryptMethod

@PostMapping(value = “test”)

@ResponseBody

public Object testEncrypt(@RequestBody UserVo user, @EncryptField String name) {

return insertUser(user, name);

}

private UserVo insertUser(UserVo user, String name) {

System.out.println(“加密后的数据:user” + JSON.toJSONString(user));

return user;

}

@Data

public class UserVo implements Serializable {

private Long userId;

@EncryptField

private String mobile;

@EncryptField

private String address;

private String age;

}

请求这个接口,看到参数被成功加密,而返回给用户的数据依然是脱敏前的数据,符合我们的预期,那到这简单的脱敏实现就完事了。

SpringBoot配置文件、隐私数据脱敏的最佳实践

SpringBoot配置文件、隐私数据脱敏的最佳实践

知其然知其所以然

========

Jasypt工具虽然简单好用,但作为程序员我们不能仅满足于熟练使用,底层实现原理还是有必要了解下的,这对后续调试bug、二次开发扩展功能很重要。

个人认为Jasypt配置文件脱敏的原理很简单,无非就是在具体使用配置信息之前,先拦截获取配置的操作,将对应的加密配置解密后再使用。

具体是不是如此我们简单看下源码的实现,既然是以springboot方式集成,那么就先从

jasypt-spring-boot-starter源码开始入手。

starter代码很少,主要的工作就是通过SPI机制注册服务和@Import注解来注入需前置处理的类

JasyptSpringBootAutoConfiguration。

SpringBoot配置文件、隐私数据脱敏的最佳实践

在前置加载类

EnableEncryptablePropertiesConfiguration中注册了一个核心处理类

EnableEncryptablePropertiesBeanFactoryPostProcessor。

SpringBoot配置文件、隐私数据脱敏的最佳实践

它的构造器有两个参数,ConfigurableEnvironment用来获取所有配属信息,

EncryptablePropertySourceConverter对配置信息做解析处理。

顺藤摸瓜发现具体负责解密的处理类

EncryptablePropertySourceWrapper,它通过对Spring属性管理类PropertySource做拓展,重写了getProperty(String name)方法,在获取配置时,凡是指定格式如ENC(x) 包裹的值全部解密处理。

SpringBoot配置文件、隐私数据脱敏的最佳实践

SpringBoot配置文件、隐私数据脱敏的最佳实践

既然知道了原理那么后续我们二次开发,比如:切换加密算法或者实现自己的脱敏工具就容易得多了。

_案例Github地址:

https://github.com/chengxy-nds/Springboot-Notebook/tree/master/springboot-jasypt_

PBE算法

再来聊一下Jasypt中用的加密算法,其实它是在JDK的JCE.jar包基础上做了封装,本质上还是用的JDK提供的算法,默认使用的是PBE算法PBEWITHMD5ANDDES,看到这个算法命名很有意思,段个句看看,PBE、WITH、MD5、AND、DES 好像有点故事,继续看。

SpringBoot配置文件、隐私数据脱敏的最佳实践

PBE算法(Password Based Encryption,基于口令(密码)的加密)是一种基于口令的加密算法,其特点在于口令是由用户自己掌握,在加上随机数多重加密等方法保证数据的安全性。

PBE算法本质上并没有真正构建新的加密、解密算法,而是对我们已知的算法做了包装。比如:常用的消息摘要算法MD5和SHA算法,对称加密算法DES、RC2等,而PBE算法就是将这些算法进行合理组合,这也呼应上前边算法的名字。

SpringBoot配置文件、隐私数据脱敏的最佳实践

既然PBE算法使用我们较为常用的对称加密算法,那就会涉及密钥的问题。但它本身又没有钥的概念,只有口令密码,密钥则是口令经过加密算法计算得来的。

口令本身并不会很长,所以不能用来替代密钥,只用口令很容易通过穷举攻击方式破译,这时候就得加点了。

盐通常会是一些随机信息,比如随机数、时间戳,将盐附加在口令上,通过算法计算加大破译的难度。

源码里的猫腻

简单了解PBE算法,回过头看看Jasypt源码是如何实现加解密的。

在加密的时候首先实例化秘钥工厂SecretKeyFactory,生成八位盐值,默认使用的

jasypt.encryptor.RandomSaltGenerator生成器。

public byte[] encrypt(byte[] message) {

// 根据指定算法,初始化秘钥工厂

final SecretKeyFactory factory = SecretKeyFactory.getInstance(algorithm1);

// 盐值生成器,只选八位

byte[] salt = saltGenerator.generateSalt(8);

//

final PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, iterations);

// 盐值、口令生成秘钥

SecretKey key = factory.generateSecret(keySpec);

// 构建加密器

final Cipher cipherEncrypt = Cipher.getInstance(algorithm1);

cipherEncrypt.init(Cipher.ENCRYPT_MODE, key);

// 密文头部(盐值)

byte[] params = cipherEncrypt.getParameters().getEncoded();

// 调用底层实现加密

byte[] encryptedMessage = cipherEncrypt.doFinal(message);

// 组装最终密文内容并分配内存(盐值+密文)

return ByteBuffer

.allocate(1 + params.length + encryptedMessage.length)

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
成长,自己不成体系的自学效果低效漫长且无助。**

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-xynQaHVp-1715077952912)]

[外链图片转存中…(img-rOJ9nDv7-1715077952913)]

[外链图片转存中…(img-gNFstU0i-1715077952913)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 27
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值