前言
在工作中遇到這樣一個(gè)問(wèn)題:開(kāi)發(fā)過(guò)程中將數(shù)據(jù)庫(kù)的賬號(hào)、密碼等信息配置在了一個(gè)單獨(dú)的properties配置文件中(使用明文)。但運(yùn)維人員要求在配置文件中的密碼一律不得出現(xiàn)明文。
環(huán)境
- spring 4.2.6.release
- mybatis 3.4.1
- druid 1.0.14
改造思路
一般spring容器啟動(dòng)時(shí),通過(guò)propertyplaceholderconfigurer類(lèi)讀取jdbc.properties文件里的數(shù)據(jù)庫(kù)配置信息。通過(guò)這個(gè)原理,我們把加密后的數(shù)據(jù)庫(kù)配置信息放到j(luò)dbc.properties文件里,然后自定義一個(gè)繼承propertyplaceholderconfigurer的類(lèi)重寫(xiě)processproperties方法,實(shí)現(xiàn)解密,把解密后的信息又放回去。
而druid已經(jīng)幫我們實(shí)現(xiàn)了上面的功能,我們只需要更改相關(guān)的配置即可。
1.生成數(shù)據(jù)庫(kù)密碼密文,替換明文。
2.更改spring配置文件中的數(shù)據(jù)源配置,開(kāi)啟數(shù)據(jù)庫(kù)密碼解密。
改造過(guò)程
生成密文
在druid-1.0.14.jar所在目錄執(zhí)行命令
java -cp druid-1.0.14.jar com.alibaba.druid.filter.config.configtools <your_db_password>
生成對(duì)應(yīng)的密文,復(fù)制到數(shù)據(jù)庫(kù)配置文件中。
更改druid數(shù)據(jù)源配置
開(kāi)啟數(shù)據(jù)庫(kù)密碼解密,在<bean id="datasource" class="com.alibaba.druid.pool.druiddatasource"></bean>
中添加如下屬性:
1
|
<property name= "connectionproperties" value= "config.decrypt=true" /> |
遇到的問(wèn)題
遇到以下錯(cuò)誤:
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
|
[ 20 / 10 / 17 12 : 30 : 29 : 029 cst] druid-connectionpool-create- 1225284770 error pool.druiddatasource: create connection error, url: jdbc:mysql: //localhost:3306/common?useunicode=true&characterencoding=utf-8 java.sql.sqlexception: access denied for user 'root' @ 'localhost' (using password: yes) at com.mysql.jdbc.sqlerror.createsqlexception(sqlerror.java: 1084 ) at com.mysql.jdbc.mysqlio.checkerrorpacket(mysqlio.java: 4232 ) at com.mysql.jdbc.mysqlio.checkerrorpacket(mysqlio.java: 4164 ) at com.mysql.jdbc.mysqlio.checkerrorpacket(mysqlio.java: 926 ) at com.mysql.jdbc.mysqlio.proceedhandshakewithpluggableauthentication(mysqlio.java: 1748 ) at com.mysql.jdbc.mysqlio.dohandshake(mysqlio.java: 1288 ) at com.mysql.jdbc.connectionimpl.coreconnect(connectionimpl.java: 2506 ) at com.mysql.jdbc.connectionimpl.connectonetryonly(connectionimpl.java: 2539 ) at com.mysql.jdbc.connectionimpl.createnewio(connectionimpl.java: 2321 ) at com.mysql.jdbc.connectionimpl.<init>(connectionimpl.java: 832 ) at com.mysql.jdbc.jdbc4connection.<init>(jdbc4connection.java: 46 ) at sun.reflect.generatedconstructoraccessor4.newinstance(unknown source) at sun.reflect.delegatingconstructoraccessorimpl.newinstance(delegatingconstructoraccessorimpl.java: 45 ) at java.lang.reflect.constructor.newinstance(constructor.java: 526 ) at com.mysql.jdbc.util.handlenewinstance(util.java: 409 ) at com.mysql.jdbc.connectionimpl.getinstance(connectionimpl.java: 417 ) at com.mysql.jdbc.nonregisteringdriver.connect(nonregisteringdriver.java: 344 ) at com.alibaba.druid.filter.filterchainimpl.connection_connect(filterchainimpl.java: 148 ) at com.alibaba.druid.filter.stat.statfilter.connection_connect(statfilter.java: 211 ) at com.alibaba.druid.filter.filterchainimpl.connection_connect(filterchainimpl.java: 142 ) at com.alibaba.druid.pool.druidabstractdatasource.createphysicalconnection(druidabstractdatasource.java: 1377 ) at com.alibaba.druid.pool.druidabstractdatasource.createphysicalconnection(druidabstractdatasource.java: 1431 ) at com.alibaba.druid.pool.druiddatasource$createconnectionthread.run(druiddatasource.java: 1861 ) |
也就是說(shuō),加解密并沒(méi)有生效,因此數(shù)據(jù)庫(kù)認(rèn)為密碼錯(cuò)誤,拒絕連接。
經(jīng)對(duì)比,發(fā)現(xiàn)數(shù)據(jù)源中的<property name="filters" value="mergestat" />
屬性值不對(duì),應(yīng)該為<property name="filters" value="stat,config" />
。
為什么filters為mergestat就不對(duì)呢?
查看src/main/java/com/alibaba/druid/filter/config/configfilter.java源碼:
在注釋43行,可以看到datasource.setfilters("config");
,因此這里不是說(shuō)mergestat不行,而是缺少config的配置。
更多配置請(qǐng)參考wiki。
總結(jié)
-
必須為spring項(xiàng)目,否則無(wú)法生效。在只含mybatis和druid(不含spring)的程序中使用上面的改造,發(fā)現(xiàn)還是無(wú)法正確連接數(shù)據(jù)庫(kù)。
-
druid datasource配置中filters屬性不應(yīng)為mergestat,否則無(wú)法生效。
-
為druid數(shù)據(jù)源打call,說(shuō)它是優(yōu)秀的java數(shù)據(jù)源一點(diǎn)也不為過(guò)。
升級(jí)druid到高版本
參考資料:druid wiki:使用configfilter
主要變化有兩處:
1.生成的密碼有公鑰、私鑰、簽名之分。
2.配置文件中需要配置簽名和公鑰,spring配置文件也需要相應(yīng)更改為:
<property name="connectionproperties" value="config.decrypt=true;config.decrypt.key=${publickey}" />
錯(cuò)誤:failed to decrypt 和 java.security.nosuchalgorithmexception:cannot find any provider supporting rsa/ecb/pkcs1padding
進(jìn)一步說(shuō)明:該問(wèn)題在eclipse直接啟動(dòng)中不會(huì)出現(xiàn),但部署到服務(wù)器上會(huì)出現(xiàn)。
原因:在解密步驟中出錯(cuò),找不到支持rsa/ecb/pkcs1padding等和解密相關(guān)的算法相關(guān)的提供者。
解決:將${java_home}\lib\ext目錄下的sunjce_provider.jar添加到classpath目錄下。
補(bǔ)充:在druid github issues中作者溫少將該問(wèn)題標(biāo)記為bug,但我認(rèn)為這只是環(huán)境問(wèn)題,不屬于druid本身的bug。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:http://www.cnblogs.com/helloIT/p/7761921.html?utm_source=tuicool&utm_medium=referral