赞
踩
一、前言
在业务系统开发过程中,我们必不可少的会使用数据库,在应用开发过程中,数据库连接信息往往都是以明文的方式配置到yaml配置文件中的,这样有密码泄露的风险,那么有没有什么方式可以避免呢?方案当然是有的,就是对数据库密码配置的时候进行加密,然后读取的时候再进行解密,这样就可以避免敏感信息泄露了。
目前市面上流行的加密算法有很多,本次我们采用国产加密算法SM4进行介绍。
SM4加密算法是一种分组对接加密算法,详细信息可以参考百度百科:
SM4:SM4百科
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcprov-jdk15to18</artifactId>
- <version>1.76</version>
- </dependency>
-
- <dependency>
- <groupId>cn.hutool</groupId>
- <artifactId>hutool-all</artifactId>
- <version>5.8.25</version>
- </dependency>
- import cn.hutool.crypto.SmUtil;
- import cn.hutool.crypto.symmetric.SM4;
-
- public class SM4Utils {
-
- /**
- * SM4是对称加密,需要设置一个加解密秘钥
- * <p>
- * System.out.println(Arrays.toString("@Jhx2024#$%^&*!+".getBytes(StandardCharsets.UTF_8)));
- * 特别注意字符串key的长度需要16位
- */
- private static final byte[] keys = new byte[]{64, 74, 104, 120, 50, 48, 50, 52, 35, 36, 37, 94, 38, 42, 33, 43};
-
- /**
- * 创建一个SM4加解密对象
- */
- private static final SM4 sm4 = SmUtil.sm4(keys);
-
- /**
- * 设置一个标识符,标识@SM4@- 开头的字符串是经过SM4加密的需要解密
- */
- public static final String SM4_PREFIX = "@SM4@-";
-
-
- /**
- * 对字符串进行加密
- *
- * @param value
- * @return
- */
- public static String encryptStr(String value) {
- // 对加密的字符串添加前缀,方便标识这是一个加密以后的字符串
- return SM4_PREFIX + sm4.encryptBase64(value);
- }
-
- /**
- * 对字符串进行解密
- *
- * @param encryptValue
- * @return
- */
- public static String decryptStr(String encryptValue) {
- // 解密时,需要去除加密标识符
- return encryptValue.startsWith(SM4_PREFIX) ? sm4.decryptStr(encryptValue.substring(SM4_PREFIX.length())) : encryptValue;
- }
- }
-
注意:字符串key的长度需要16位,否则会报错
:
- Exception in thread "main" cn.hutool.crypto.CryptoException: InvalidKeyException: SM4 requires a 128 bit key
- at cn.hutool.crypto.symmetric.SymmetricCrypto.encrypt(SymmetricCrypto.java:277)
- at cn.hutool.crypto.symmetric.SymmetricEncryptor.encrypt(SymmetricEncryptor.java:139)
- at cn.hutool.crypto.symmetric.SymmetricEncryptor.encryptBase64(SymmetricEncryptor.java:159)
- at com.learn.util.SM4Utils.encryptStr(SM4Utils.java:34)
- at com.learn.SnowFlakeDemoApplication.main(SnowFlakeDemoApplication.java:17)
- Caused by: java.security.InvalidKeyException: SM4 requires a 128 bit key
- at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineInit(Unknown Source)
- at javax.crypto.Cipher.init(Cipher.java:1246)
- at javax.crypto.Cipher.init(Cipher.java:1186)
- at cn.hutool.crypto.CipherWrapper.initMode(CipherWrapper.java:116)
- at cn.hutool.crypto.symmetric.SymmetricCrypto.initMode(SymmetricCrypto.java:415)
- at cn.hutool.crypto.symmetric.SymmetricCrypto.encrypt(SymmetricCrypto.java:274)
- ... 4 more
测试代码
- String str = "hello, world";
- System.out.println("原始字符串: " + str);
- str = SM4Utils.encryptStr(str);
- System.out.println("经过SM4默认秘钥加密字符串: " + str);
- str = SM4Utils.decryptStr(str);
- System.out.println("经过SM4默认秘钥解密字符串: " + str);
测试结果
对数据库配置信息进行加密,加密信息的生成需要使用我们自定义的SM4Utils工具类
:
- spring:
- datasource:
- url: jdbc:mysql://127.0.0.1:3306/uid
- username: '@SM4@-tWyNqklSTiV5W3gN4dTQ2g=='
- password: '@SM4@-tWyNqklSTiV5W3gN4dTQ2g=='
此时,启动项目,数据库信息加载时,肯定会报错:
针对加密的数据库配置信息,需要自定义解密,所以需要自定义一个DataSource对象
:
- import com.learn.util.SM4Utils;
- import com.zaxxer.hikari.HikariDataSource;
-
- public class MyHikariDataSource extends HikariDataSource {
-
- @Override
- public String getUsername() {
- // 对用户名进行解密
- return SM4Utils.decryptStr(super.getUsername());
- }
-
- @Override
- public String getPassword() {
- // 对密码进行解密
- return SM4Utils.decryptStr(super.getPassword());
- }
- }
- spring:
- datasource:
- url: jdbc:mysql://127.0.0.1:3306/uid
- username: '@SM4@-tWyNqklSTiV5W3gN4dTQ2g==' # 经过SM4Utils.encryptStr方法加密
- password: '@SM4@-tWyNqklSTiV5W3gN4dTQ2g==' # 经过SM4Utils.encryptStr方法加密
- type: com.learn.db.MyHikariDataSource # 指定自定义的DataSource类
注意:我这里是使用的spring boot默认HikariDataSource数据源,所以自定义DataSource继承HikariDataSource类,如果是其他数据源,比如druid数据源,继承Druid的DruidDataSource类即可。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。