一、Spring开发加密
在实际开发过程中,我们经常需要遇到数据源等资源的配置,最方便快捷的做法就是将这些配置信息独立到一个外部属性文件中。我们可以创建一个名为application.properties的文件。
通过getPropertyValue方法,将第一张图片中属性值对应的属性名称入参,如oracle.datasource.username即可得到输出QC。
但是通常情况下,对于这些敏感的属性信息,我们都将会以密文的形式进行保存。
那解决思路就是对属性文件中的属性值进行加密,让Spring容器在读取属性之后再进行解密。
信息加密分两种,分别为对称和非对称,前者表示加密后的信息能够解密成原值,后者则不能。我们所熟悉的MD5加密就属于非对称加密,DES则属于对称加密,因此根据此次的要求,我们选择DES对称加密。需要在pom.xml中添加依赖
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
加密解密代码如下:
public class DESUtils {
// 指定DES加密解密所用的秘钥
private static Key key;
// 加密用KEY
private static String KEY_STR = "dashuaigege19931130";
static {
try {
KeyGenerator generator = KeyGenerator.getInstance("DES");
generator.init(new SecureRandom(KEY_STR.getBytes()));
key = generator.generateKey();
generator = null;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 对字符串进行DES加密,返回BASE64编码的加密字符串
public static String getEncryptString(String str) {
Base64 base64 = new Base64();
try {
byte[] strBytes = str.getBytes("UTF8");
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptStrBytes = cipher.doFinal(strBytes);
return base64.encodeToString(encryptStrBytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 对BASE64编码的加密字符串进行解密,返回解密后的字符串
public static String getDecryptString(String str) {
Base64 base64 = new Base64();
try {
byte[] strBytes = base64.decode(str);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptStrBytes = cipher.doFinal(strBytes);
return new String(decryptStrBytes, "UTF8");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 对入参的字符串进行加密,打印加密后的串
public static void main(String[] args) {
System.out.println("我要加密了喔!!!");
String str = "不爱我就拉倒!!!";
String encryptString = getEncryptString(str);
System.out.println(str + ":" + encryptString);
System.out.println("我要解密了喔!!!");
System.out.println(encryptString + ":" + getDecryptString(encryptString));
}
}
运行之后结果如下:
接下来,我们只需要对上图中得属性的代码进行小小改动,通过属性名称判断此次属性值是否需要解密来进行对应的操作即可。
二、SpringBoot开发加密
在SpringBoot开发过程中,我们往往将很多第三方配置信息写在application配置文件中,比如SpringBoot JPA需要的
spring.datasource.url,spring.datasource.username,spring.datasource.password等。
这时候采用上面一种的方法步骤将会变得麻烦可以采用如下方法。
1.pom引用:
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
注意此处的版本号。因为版本号不对,会引发下面的代码配置出现
在application配置文件中添加如下配置:
jasypt.encryptor.password=hellospringboot
此处的配置相当于进行加密处理时所采用的的KEY值。
此时,Test运行如下代码:
// 注入StringEncryptor
@Autowired
private StringEncryptor encryptor;
@Test
public void contextLoads() {
// 加密root
String username = encryptor.encrypt("root");
System.out.println(username);
// 加密123
String password = encryptor.encrypt("123");
System.out.println(password);
// System.out.println(value + " " + user + " " + password);
}
会得到加密后的结果输出,说明加密成功
但是将加密用KEY值写在配置文件中,总会让人觉得不安全,或者重写加密解密过程,那么可以添加如下代码:
public class MyEncryptablePropertyResolver implements EncryptablePropertyResolver {
private final PooledPBEStringEncryptor encryptor;
public MyEncryptablePropertyResolver(char[] password) {
this.encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPasswordCharArray(password);
config.setAlgorithm("PBEWithMD5AndDES");
config.setKeyObtentionIterations("1000");
config.setPoolSize(1);
config.setProviderName("SunJCE");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
config.setIvGeneratorClassName("org.jasypt.salt.NoOpIVGenerator");
config.setStringOutputType("base64");
encryptor.setConfig(config);
}
@Override
public String resolvePropertyValue(String value) {
if (value != null && value.startsWith("ENC(")) {
return encryptor.decrypt(value.substring("ENC(".length(), value.length() - 1));
}
return value;
}
}
@Configuration
public class EncryptorConfiguration {
@Bean(name = "encryptablePropertyResolver")
EncryptablePropertyResolver encryptablePropertyResolver() {
return new MyEncryptablePropertyResolver("hellospringboot".toCharArray());
}
}
此时将之前得到加密后的密文写在配置文件中,我们运行后即可解密,此处注意,添加的ENC()可在代码中自行配置,为了验证ENC的作用,此处wongws.user值特意不加:
wongws.user=9CsUUXa1UXMhd7SM72afBg==
wongws.password=ENC(Pu6As2pPOXNrdct5DSKsnQ==)
@Value("${wongws.user}")
private String user;
@Value("${wongws.password}")
private String password;
@Test
public void contextLoads() {
System.out.println(user + " " + password);
}
成功。