抚松做网站wordpress小程序二开
news/
2025/9/29 20:17:27/
文章来源:
抚松做网站,wordpress小程序二开,icp域名备案查询,wordpress个性主题这几天公司在排查内部数据账号泄漏#xff0c;原因是发现某些实习生小可爱居然连带着账号、密码将源码私传到GitHub上#xff0c;导致核心数据外漏#xff0c;孩子还是没挨过社会毒打#xff0c;这种事的后果可大可小。说起这个我是比较有感触的#xff0c;之前我TM被删库… 这几天公司在排查内部数据账号泄漏原因是发现某些实习生小可爱居然连带着账号、密码将源码私传到GitHub上导致核心数据外漏孩子还是没挨过社会毒打这种事的后果可大可小。说起这个我是比较有感触的之前我TM被删库的经历到现在想起来心里还难受我也是把数据库账号明文密码误提交到GitHub然后被哪个大宝贝给我测试库删了后边我长记性了把配置文件内容都加密了数据安全问题真的不容小觑不管工作汇还是生活敏感数据一定要做脱敏处理。所以接下来咱们需要开展两方面的工作对配置文件进行脱敏操作对敏感的数据库字段进行脱敏操作。说干就干接下来咱们一起来对项目进行脱敏操作。1.配置脱敏实现配置的脱敏我使用了Java的一个加解密工具Jasypt它提供了单密钥对称加密和非对称加密两种脱敏方式。单密钥对称加密一个密钥加盐可以同时用作内容的加密和解密依据非对称加密使用公钥和私钥两个密钥才可以对内容加密和解密以上两种加密方式使用都非常简单咱们以springboot集成单密钥对称加密方式做示例。首先引入jasypt-spring-boot-starter jar !--配置文件加密--dependencygroupIdcom.github.ulisesbocchio/groupIdartifactIdjasypt-spring-boot-starter/artifactIdversion2.1.0/version/dependency
配置文件加入秘钥配置项jasypt.encryptor.password并将需要脱敏的value值替换成预先经过加密的内容ENC(mVTvp4IddqdaYGqPl9lCQbzM3H/b0B6l)。这个格式我们是可以随意定义的比如想要abc[mVTvp4IddqdaYGqPl9lCQbzM3H/b0B6l]格式只要配置前缀和后缀即可。jasypt:encryptor:property:prefix: abc[suffix: ]
ENC(XXX格式主要为了便于识别该值是否需要解密如不按照该格式配置在加载配置项的时候jasypt将保持原值不进行解密。spring:datasource:url: jdbc:mysql://1.2.3.4:3306/xiaofu?useSSLfalseuseUnicodetruecharacterEncodingUTF-8autoReconnecttrueze oDateTimeBehaviorconvertToNullserverTimezoneAsia/Shanghaiusername: xiaofupassword: ENC(mVTvp4IddqdaYGqPl9lCQbzM3H/b0B6l)# 秘钥
jasypt:encryptor:password: 程序员内点事(然而不支持中文)
秘钥是个安全性要求比较高的属性所以一般不建议直接放在项目内可以通过启动时-D参数注入或者放在配置中心避免泄露。java -jar -Djasypt.encryptor.password1123 springboot-jasypt-2.3.3.RELEASE.jar
预先生成的加密值可以通过代码内调用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 inputroot passwordxiaofu algorithmPBEWithMD5AndDES
一顿操作后如果还能正常启动说明配置文件脱敏就没问题了。2.敏感字段脱敏生产环境用户的隐私数据比如手机号、身份证或者一些账号配置等信息入库时都要进行不落地脱敏也就是在进入我们系统时就要实时的脱敏处理。用户数据进入系统脱敏处理后持久化到数据库用户查询数据时还要进行反向解密。这种场景一般需要全局处理那么用AOP切面来实现在适合不过了。首先自定义两个注解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-jasyptSlf4j
Aspect
Component
public class EncryptHandler {Autowiredprivate 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;EncryptFieldprivate String mobile;EncryptFieldprivate String address;private String age;
}
请求这个接口看到参数被成功加密而返回给用户的数据依然是脱敏前的数据符合我们的预期那到这简单的脱敏实现就完事了。3.原理分析Jasypt工具虽然简单好用但作为程序员我们不能仅满足于熟练使用底层实现原理还是有必要了解下的这对后续调试bug、二次开发扩展功能很重要。个人认为Jasypt配置文件脱敏的原理很简单无非就是在具体使用配置信息之前先拦截获取配置的操作将对应的加密配置解密后再使用。具体是不是如此我们简单看下源码的实现既然是以springboot方式集成那么就先从jasypt-spring-boot-starter源码开始入手。starter代码很少主要的工作就是通过SPI机制注册服务和Import注解来注入需前置处理的类JasyptSpringBootAutoConfiguration。在前置加载类EnableEncryptablePropertiesConfiguration中注册了一个核心处理类EnableEncryptablePropertiesBeanFactoryPostProcessor。它的构造器有两个参数ConfigurableEnvironment用来获取所有配属信息EncryptablePropertySourceConverter对配置信息做解析处理。顺藤摸瓜发现具体负责解密的处理类EncryptablePropertySourceWrapper它通过对Spring属性管理类PropertySourceT做拓展重写了getProperty(String name)方法在获取配置时凡是指定格式如ENC(x) 包裹的值全部解密处理。既然知道了原理那么后续我们二次开发比如切换加密算法或者实现自己的脱敏工具就容易的多了。“案例Github地址https://github.com/chengxy-nds/Springboot-Notebook/tree/master/springboot-jasyptPBE算法再来聊一下Jasypt中用的加密算法其实它是在JDK的JCE.jar包基础上做了封装本质上还是用的JDK提供的算法默认使用的是PBE算法PBEWITHMD5ANDDES看到这个算法命名很有意思段个句看看PBE、WITH、MD5、AND、DES 好像有点故事继续看。PBE算法Password Based Encryption基于口令密码的加密是一种基于口令的加密算法其特点在于口令是由用户自己掌握在加上随机数多重加密等方法保证数据的安全性。PBE算法本质上并没有真正构建新的加密、解密算法而是对我们已知的算法做了包装。比如常用的消息摘要算法MD5和SHA算法对称加密算法DES、RC2等而PBE算法就是将这些算法进行合理组合这也呼应上前边算法的名字。既然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).put((byte) params.length).put(params).put(encryptedMessage).array();
}
由于默认使用的是随机盐值生成器导致相同内容每次加密后的内容都是不同的。那么解密时该怎么对应上呢看上边的源码发现最终的加密文本是由两部分组成的params消息头里边包含口令和随机生成的盐值encryptedMessage密文。加密而在解密时会根据密文encryptedMessage的内容拆解出params内容解析出盐值和口令在调用JDK底层算法解密出实际内容。Override
SneakyThrows
public byte[] decrypt(byte[] encryptedMessage) {// 获取密文头部内容int paramsLength Byte.toUnsignedInt(encryptedMessage[0]);// 获取密文内容int messageLength encryptedMessage.length - paramsLength - 1;byte[] params new byte[paramsLength];byte[] message new byte[messageLength];System.arraycopy(encryptedMessage, 1, params, 0, paramsLength);System.arraycopy(encryptedMessage, paramsLength 1, message, 0, messageLength);// 初始化秘钥工厂final SecretKeyFactory factory SecretKeyFactory.getInstance(algorithm1);final PBEKeySpec keySpec new PBEKeySpec(password.toCharArray());SecretKey key factory.generateSecret(keySpec);// 构建头部盐值口令参数AlgorithmParameters algorithmParameters AlgorithmParameters.getInstance(algorithm1);algorithmParameters.init(params);// 构建加密器调用底层算法final Cipher cipherDecrypt Cipher.getInstance(algorithm1);cipherDecrypt.init(Cipher.DECRYPT_MODE,key,algorithmParameters);return cipherDecrypt.doFinal(message);
}
解密我是磊哥如果对你有用在看、关注支持下咱们下期见~
往期推荐
SpringBoot 如何统一后端返回格式老鸟们都是这样玩的SpringBoot时间格式化的5种方法SpringBoot 优雅的参数效验
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/922220.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!