druid是阿里巴巴出品的一款开源的数据库连接池,其一大优势在于监控。
将数据库配置信息,数据库连接的用户名和密码明文配置在配置文件,是一种不安全的做法。
很多行业规范要求配置文件不得明文存储数据库连接密码,这里,就来探究下如何使用druid加密数据库配置和密码。
既然是实战性质的博文,那就废话不多说,来暴力的,首先看段代码,
1. Druid提供了哪些机制可供自定义
位于 DruidAbstractDataSource.java
:
|
|
这段代码得到的信息如下:
- createPhysicalConnection暗示着创建数据库连接时会调用此函数。
- 如果userCallback存在,则调用UserCallback来取得数据库连接的用户名。
- 如果passwordCallback存在,则调用passwordCallback来取得数据库连接的密码。
- 总之,以上两个callback提供了能自定义用户名和密码的hook,非常灵活。
既然提供了hook,那么使用自定义的加密方法来加密数据库连接配置的用户名和密码也就非常轻松了。
2. 在什么地方对DruidDataSource进行自定义
首先,我们需要一个地方能将callback给设置进去。DruidDataSource实现了DataSource接口,如下:
- 在这里,我们声明了Bean DataSource,实际使用的实现类是DruidDataSource。与此同时,将配置文件中的druid配置也注入了进去。
- 既然在初始化能拿到DruidDataSource对象,显然,使用setter方法就能把callback设置进去。
最后一步,实现callback。
从形而上的方面来说,理想的callback是提供若干信息作为输入,得到所需信息的函数。
然而,java作为OOP语言,不得不将callback以对象形式展现。
再回顾文章初的代码,我们可以发现:
- 对于passwordCallback,其提供了connectProperties作为输入参数。那么,我们可以从这里得到计算密码所需的必要信息。
- 遗憾的是,对于userCallback,并没有传入必要的参数用以计算密码。
3. callback如何实现
为了解决问题2,如果callback是函数,将信息放入闭包中即可解决。不够这里是java,那么就能继承callback,从构造函数传入。
这样,callback大概长这样(一个尽量精简的例子):
|
|
- callback中可以自由选择解密的方法,对称可以,非对称也行,拿AWS远程解密也不错。只要库提供了这个机制,灵活性和扩展性就十分的强。
3.1. 加密后的配置信息如何对接
最后,创建callback时,就要把必须信息传入:
- 加密后的数据库用户名和密码放入配置文件中,从上面可以看到,这些配置从配置文件中注入,最终传入到callabck中保存。
- 这些自定义注入的信息是传入callback中,由callback将其计算成明文用户名和密码。
由于提供给callback的配置和callback本身都是自定义的,因此,理论上这种方式可满足各式各样的加密实现需求,非常具有灵活性。
3.2. 最后
以上探究了非常具有灵活性的自定义加密的方案,
实际上,druid提供的ConfigFilter过滤器也能提供一个固定的加密需求实现。
如果要求不高,用ConfigFilter也是一种选择。
不过,druid拥有的过滤器功能使我想到,能否通过自定义druid的过滤器实现本文的需求呢?
等到以后有时间再来探究一番。