读取加密的properties文件

/ Spring / 没有评论 / 383浏览

在上一篇中我们知道了在spring中可以用很多种方式来读取properties配置文件,但是在上一篇中我们加载的properties文件的信息都是明文存储的,但在实际的项目开发中,常常会涉及到一些敏感数据是不能够明文存储的,例如生产环境的数据库连接。为了保证安全和不被泄漏,这时我们就要对properties文件的信息进行加密处理,然后在使用时在进行解密。所以接下来我们将通过spring框架实现上述的逻辑。

加解密工具类:

public class DESUtils {
private static Key key;
private static String SECRET_KEY = "jilinwula";

static {
try {
KeyGenerator generator = KeyGenerator.getInstance("DES");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(SECRET_KEY.getBytes());
generator.init(secureRandom);
key = generator.generateKey();
generator = null;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}

public static String getEncryptString(String value) {
BASE64Encoder base64Encoder = new BASE64Encoder();
try {
byte[] valueBytes = value.getBytes("UTF-8");
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptValueBytes = cipher.doFinal(valueBytes);
return base64Encoder.encode(encryptValueBytes);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}

public static String getDecryptString(String value) {
BASE64Decoder base64Decoder = new BASE64Decoder();
try {
byte[] valueBytes = base64Decoder.decodeBuffer(value);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptValueBytes = cipher.doFinal(valueBytes);
return new String(decryptValueBytes, "UTF-8");
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}
}

spring没有为我们提供可以直接解密properties文件的接口,但我们可以继承PropertyPlaceholderConfigurer类然后我们自己处理需要解密的属性。具体代码如下:

public class EncryptPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
@Override
protected String convertProperty(String propertyName, String propertyValue) {
if ("app.password".equals(propertyName)) {
return DESUtils.getDecryptString(propertyValue);
}
return propertyValue;
}
}

下面是properties文件,我们已经将app.password属性通过上面的工具类加密,这样即使其它人获取到该配置文件,也无法成功连接到数据库。

app.username=admin
app.password=Sv14PZ8yRDg=
app.nickname=吉林乌拉

下面代码,和上篇中读取文件的代码一致。

@Component
public class User {

@Value("${app.username}")
private String username;

@Value("${app.password}")
private String password;

@Value("${app.nickname}")
private String nickname;

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getNickname() {
return nickname;
}

public void setNickname(String nickname) {
this.nickname = nickname;
}

@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}
<bean class="com.jilinwula.spring.EncryptPropertyPlaceholderConfigurer" p:location="classpath:app.properties" p:fileEncoding="utf-8"/>

<context:component-scan base-package="com.jilinwula.spring"/>

上面的EncryptPropertyPlaceholderConfigurer类为我们自己实现的,否则解密操作并不会成功。

@Test
public void test() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
User user = applicationContext.getBean("user", User.class);
System.out.println(user);
}
User{username='admin', password='root', nickname='吉林乌拉'}

看输出结果,此时的password已经是解密成功的了。