前言
我们在系统中,可能需要针对配置文件的敏感信息,如数据库的账号密码等进行使用密文存储,这个时候就需要用到配置文件加解密的技术。话不多说,直接说明开整,我这里是引用jasypt实现加解密。
1.引入依赖
<!-- Jasypt依赖, 自定义解密 -->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot</artifactId>
<version>3.0.4</version>
</dependency>
2.编写解密类
实现StringEncryptor类,具体使用什么加解密的方法可根据实际情况来,我这里举例是使用Rsa加密。
@Slf4j
public class RsaEncryptor implements StringEncryptor {
static final Base64.Encoder encoder = Base64.getEncoder();
static final Base64.Decoder decoder = Base64.getDecoder();
private static final String PRIVATE_KEY = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJHDLB1Tzvs/kVfjOWCgcVQdd+bR+yr/4W+PTDW96G+mRkJa54+BnR6uhIyQf2czIo1Mlde7sbjqHuapTNMDZolqAIWBIfzw/RbqM/llySTg+zwlVfI25Zecxdmfk/lTgquIPCnagRMC+PE08AasHw8wSfb04OGUQR3G28Huf4DpAgMBAAECgYAoeKTkhbMYDqfX27bALfwZa08xzwaqgz6AP6zc1RxW97dVUDEwJsBN1w3li29cY5XJ3sRSEILBgXvP9pzmj/CldmViK31svDuedrzzrG4wiw0jCgO/vp4Fy0aBC6jY1i9Nc2rMCHOr+ftccEw9TAp088cM++/wffEtuF4D8SZwewJBAMk+c2pMa0Kz55HFUZKHPeS9I9hzuxiAxsfc/alH/uHv9mmRDZQGjVx2i+H3p8eDQFHcS8BUn64O4AZavtMnplcCQQC5bC5BowKfItEmn5g179G1zGB4ZqPHnVveK2ukjzvFW13ZU98bv8+mOSYG7TvoSoFpIY3CgGQ6dT2nILqjDQq/AkAJkkPRAXN0h7Py1eysSGxkLa6/w7lZT/6kUNlrrLXtrwkMOk7oBGvCwwyiIbJEJfTwL8cWja/OinyTMMu0pUUfAkEApVQ7LlUtqjz+JiUZL8aEw0fXIKPMFtlNJ5ypnxIDpmZgGL566aAugzTjnjt7NhTwrI+5eZrHQ4R0E4fQQkAHuwJBAIc6d5POlHAMJs9U2zTpjeKOBJXa8MplYkj2s0vTz32A/fVGwSEknxCp7OWIUKLQTB9WgBDAN/4uYThFG7EE5Uc=";
private static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCRwywdU877P5FX4zlgoHFUHXfm0fsq/+Fvj0w1vehvpkZCWuePgZ0eroSMkH9nMyKNTJXXu7G46h7mqUzTA2aJagCFgSH88P0W6jP5Zckk4Ps8JVXyNuWXnMXZn5P5U4KriDwp2oETAvjxNPAGrB8PMEn29ODhlEEdxtvB7n+A6QIDAQAB";
private static final RSA RSA = new RSA(PRIVATE_KEY, PUBLIC_KEY);
@Override
public String encrypt(String source) {
// 加密方法
return encoder.encodeToString(RSA.encrypt(source, Charsets.UTF_8, KeyType.PublicKey));
}
@Override
public String decrypt(String source) {
// 解密方法
return new String(RSA.decrypt(decoder.decode(source),KeyType.PrivateKey),Charsets.UTF_8);
}
}
3.编写配置类
@Configuration
@Import(EnableEncryptablePropertiesConfiguration.class)
public class EncryptConfig {
@Bean("jasyptStringEncryptor")
public StringEncryptor rsaEncryptor(){
// 返回我们刚刚编写的解密类
return new RsaEncryptor();
}
}
4.yml中配置
只需要将要加密的内容,使用对应方法解密后,使用ENC(密文)包裹起来然后填写在配置文件中即可。举例:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test1?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&useAffectedRows=true&useSSL=false
username: ENC(BhB1LSI0949Qf3a/H8QGEhH3jPBhR1NgpMJ/CPm8o8trH4g1utkNkX4hSGLhgsDePTOdri1myaqJhHaib3k1wy1m0eTC4WtJLLvckcBr0S/ykSLjrRM6JP/FpNNJeNIRAHD5IFR60fTwOjY+x7Thy3UfEZL2QVA1qAzxtVR6a10=)
password: ENC(gy3bvOIypy8KxhAKEWPGiyQHzS7rhypbwHTbsiDuWdn/Lc+1Do5xZkIauca5STwL3teM966Pv5PjzTaVwD0rLb/oE5SKlgMVRD8Qbq6QwQNHh043ziB9Nc+9r15Qbqv0QMF4gWbPTnwcPsayQnGlcusEseUpO3r77iGv/2e2jAY=)
5.其它
如果你觉得你配置文件不想要ENC()包裹,想要其他的指定前缀啥的话,可以实现EncryptablePropertyResolver类,如我这里是使用正则匹配ENCODE()
@Component
public class MyEncryptPropertyResolver implements EncryptablePropertyResolver {
/**
* 默认密钥
*/
@Value("${custom.secret-key:1234567812345678}")
private String sk;
/**
* 自定义密码正则 ENCDOE(xxxx)
*/
private static final Pattern pattern = Pattern.compile("^ENCODE\\((.*)\\)$");
@Override
public String resolvePropertyValue(String value) {
if (value != null) {
// 正则校验
Matcher matcher = pattern.matcher(value);
// 匹配到了ENCODE(开头 )结尾
if (matcher.matches()) {
// 获取括号内的密文
String group = matcher.group(1);
// 解密
return SmStrUtil.sm4DecryptStr(group, sk);
}
return value;
}
return null;
}
}
同样的,需要编写对应的配置类:
@Component
public class Encryptor {
/**
* 重载bean名称,这样服务重启时会找该bean名, bean不能动
* 默认yml文件里面是需要jasypt:encryptor:bean:自定义bean名称, 不指定则默认encryptablePropertyResolver
* @date 2023/5/11 20:00
* @return 自定义解密字符串
*/
@Bean(name="encryptablePropertyResolver")
EncryptablePropertyResolver encryptablePropertyResolver(){
return new MyEncryptPropertyResolver();
}
}