springboot的配置加密(一)之druid

背景

不止一次碰到小伙伴询问如下问题 我把数据库密码和用户名写在配置文件里 会不会不安全~

想当然 肯定是不安全的 万一提交了配置文件那么生产环境的用户名和密码不就泄露了么???

倒不是不信任小伙伴 不过由于未隔离造成的事件真是太多了~因此权限需要严格把控 http://news.sina.com.cn/o/2018-06-05/doc-ihcqccin5836273.shtml

分析

一般来说那些数据需要加密呢???

典型的包括db配置 第三方安全key配置等等

关于db配置的加密 其实druid提供了一个简单的密码回调来完成

首先看看druid的解决方案~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class DruidPasswordCallback extends PasswordCallback {
private static final long serialVersionUID = 1L;
private String url;
private Properties properties;
public DruidPasswordCallback(){
this("druidDataSource password", false);
}
public DruidPasswordCallback(String prompt, boolean echoOn){
super(prompt, echoOn);
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
}

其继承了java的passwordCallback方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public PhysicalConnectionInfo createPhysicalConnection() throws SQLException {
String url = this.getUrl();
Properties connectProperties = getConnectProperties();
String password = getPassword();
PasswordCallback passwordCallback = getPasswordCallback();
if (passwordCallback != null) {
if (passwordCallback instanceof DruidPasswordCallback) {
DruidPasswordCallback druidPasswordCallback = (DruidPasswordCallback) passwordCallback;
druidPasswordCallback.setUrl(url);
druidPasswordCallback.setProperties(connectProperties);
}
char[] chars = passwordCallback.getPassword();
if (chars != null) {
password = new String(chars);
}
}
//省略
return new PhysicalConnectionInfo(conn, connectStartNanos, connectedNanos, initedNanos, validatedNanos);
}

很明显可以看到了password将由getPassword提供。因此我们需要自己继承DruidPasswordCallback完成password的获取

方案

  1. 可以自定义passwordcallback 通过某种服务去获取到密码~
  2. 自定义passwordcallback通过解码获得密码
  3. 其他形式

此时我们选择解密的形式【这样尽量最少依赖】

在配置数据源的时候我们可以配置密码密文为

1
<property name="connectionProperties" value="password=${db.password}"/>

由于druid在初始化的时候将connectionProperties传递到passwordCallback中 此时在callback中可以利用一些方法完成密码的获得。

那么我们实现一个callback

1
2
3
4
5
6
7
8
9
10
public class F6carPasswordCallback extends DruidPasswordCallback {
@Override
public void setProperties(Properties properties) {
super.setProperties(properties);
String password = (String) properties.get("password");
String dbpassword= decrypt(password);
setPassword(dbpassword.toCharArray());
}
}

这样就完成了密码的加解密~

弊端

和实现进行绑定 并且无法对于其他字段进行加密