背景
現(xiàn)在的開發(fā)習(xí)慣敛惊,無論是公司的項目還是個人的項目渊鞋,都會選擇將源碼上傳到 Git 服務(wù)器(GitHub、Gitee 或是自建服務(wù)器)瞧挤,但只要將源碼提交到公網(wǎng)服務(wù)器就會存在源碼泄漏的風(fēng)險锡宋,而數(shù)據(jù)庫配置信息作為源碼的一部分,一旦出現(xiàn)源碼泄漏特恬,那么數(shù)據(jù)庫中的所有數(shù)據(jù)都會公之于眾执俩,其產(chǎn)生的不良后果無法預(yù)期(比如某某酒店的信息)
于是為了避免這種問題的產(chǎn)生,我們至少要對數(shù)據(jù)庫的密碼進(jìn)行加密操作癌刽,這樣即使得到了源碼役首,也不會造成數(shù)據(jù)的泄露,也算保住了最后一塊遮羞布
如何加密
對于 Java 項目來說显拜,要想快速實現(xiàn)數(shù)據(jù)庫的加密衡奥,最簡單可行的方案就是使用阿里巴巴提供的 Druid 來實現(xiàn)加密
什么是Druid
Druid(中文譯為“德魯伊”)是阿里巴巴開源的一款 Java 語言中最好的數(shù)據(jù)庫連接池
Druid 提供了強(qiáng)大的監(jiān)控和擴(kuò)展功能,當(dāng)然也包含了數(shù)據(jù)庫的加密功能
功能
Druid 可以監(jiān)控數(shù)據(jù)庫訪問性能远荠,Druid 內(nèi)置提供了一個功能強(qiáng)大的 StatFilter 插件矮固,能夠詳細(xì)統(tǒng)計 SQL 的執(zhí)行性能,這對于線上分析數(shù)據(jù)庫訪問性能有幫助
替換數(shù)據(jù)庫連接池 DBCP 和 C3P0譬淳,Druid 提供了一個高效档址、功能強(qiáng)大盹兢、可擴(kuò)展性好的數(shù)據(jù)庫連接池
數(shù)據(jù)庫密碼加密,直接把數(shù)據(jù)庫密碼寫在配置文件中辰晕,這是不好的行為,容易導(dǎo)致安全問題确虱。DruidDriver 和 DruidDataSource 都支持 PasswordCallback
SQL 執(zhí)行日志含友,Druid 提供了不同的 LogFilter,能夠支持 Common-Logging校辩、Log4j 和 JDKLog窘问,你可以按需要選擇相應(yīng)的 LogFilter,監(jiān)控你應(yīng)用的數(shù)據(jù)庫訪問情況
擴(kuò)展 JDBC宜咒,如果你要對 JDBC 層有編程的需求惠赫,可以通過 Druid 提供的 Filter-Chain 機(jī)制,很方便編寫 JDBC 層的擴(kuò)展插件
加密執(zhí)行流程
在沒有進(jìn)行密碼加密之前故黑,項目的交互流程是這樣的:
在使用了密碼加密之后儿咱,項目的交互流程就變成了這樣:
使用Druid實現(xiàn)加密
添加Druid依賴
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.5</version></dependency>
生成密文
Druid 添加完成之后就可以借助 Druid 中提供的 ConfigTools 類來加密密碼了,實現(xiàn)代碼如下:
importcom.alibaba.druid.filter.config.ConfigTools;classMyTests{publicstaticvoidmain(String[]args)throws Exception{// 需要加密的明文命名String password="youPassword";// 【注意:這里要改為你自己的密碼】// 調(diào)用 druid 生成私鑰场晶、公鑰混埠、密文ConfigTools.main(newString[]{password});}}
以上代碼執(zhí)行的結(jié)果如下:
privateKey:MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEApOjcMWSDzJiKVGmtcBBoQPtM9tVW2H2cnS6xZK7NrbzQXYWLQD2zefIrrx9vMvqRIHEqkmAHTuUcUXHgCxu0cwIDAQABAkAlqo5ItdWo0Jqf5zdXJlg5p2yP4HCiqCYyfKzF+2s9KEmgWZJWTctZDsgQ0iYUohORR59I+J4nabhel1x5/INpAiEA6jwSyFqMUPOh1XlrzNFek+RthOQ5n4+ALPo+vULayO0CIQC0O7JM9sIq+tg+jCGv+ypk6vbuRKY9m5W2rSRXapGm3wIgRHul3jAjIDPrF/f1HaAFL+Y0Yws7Ebyp8/yCRWF7iA0CIALbe20q8FMcHPeI4zPWCIsHCpkmb3hEkjAOOKhGIT8DAiAqiUuz92NqKeyjmOfons1ka65EzVwA3NDhZ6+IQcnuig== publicKey:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKTo3DFkg8yYilRprXAQaED7TPbVVth9nJ0usWSuza280F2Fi0A9s3nyK68fbzL6kSBxKpJgB07lHFFx4AsbtHMCAwEAAQ== password:IMgKm27bOHok3/+5aDL4jGBoVVZkpicbbM6pIXQppi3dI7h3jngSAqhqwqYnfuYpyVJ0k++q9xWWnHtd6sAWnQ==
從上述結(jié)果可以看出,使用 ConfigTools 類會生成 3 部分的內(nèi)容:
privateKey:私鑰诗轻,暫時不會用到钳宪,用于密碼的加密;
publicKey:公鑰扳炬,用于密碼的解密吏颖;
password:加密之后的密碼。
添加配置
完成了以上操作之后恨樟,只需要將上一步生成的公鑰和密文添加到項目的配置文件 application.yml(或application.xml)中就實現(xiàn)了加密操作了半醉,具體配置信息如下:
spring:# MySQL 配置datasource:driver-class-name:com.mysql.cj.jdbc.Drivertype:com.alibaba.druid.pool.DruidDataSourcedruid:url:jdbc:mysql://127.0.0.1:3306/testdb?serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&useSSL=falseusername:root? ? ? password:IMgKm27bOHok3/+5aDL4jGBoVVZkpicbbM6pIXQppi3dI7h3jngSAqhqwqYnfuYpyVJ0k++q9xWWnHtd6sAWnQ==# encrypt configfilters:config? ? ? connect-properties:config.decrypt:trueconfig.decrypt.key:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKTo3DFkg8yYilRprXAQaED7TPbVVth9nJ0usWSuza280F2Fi0A9s3nyK68fbzL6kSBxKpJgB07lHFFx4AsbtHMCAwEAAQ==
其中 password 對應(yīng)的是上一步生成的 password(密文),而 config.decrypt.key 對應(yīng)的是上一步生成的 publicKey(公鑰)劝术,如下圖所示:
這里提供一個原始的配置文件奉呛,以便和加密后的配置文件進(jìn)行比對:
注意事項-插著鑰匙的鎖
經(jīng)過前面 3 步的配置之后,我們的程序就可以正常運(yùn)行了夯尽,但這遠(yuǎn)沒有結(jié)束瞧壮!
在第 3 步配置時,我們將密文和公鑰都寫入配置文件匙握,這就會造成當(dāng)有人拿到密文和公鑰之后咆槽,就可以使用 Druid 將加密的密碼還原出來了,這就好比一把插著鑰匙的鎖是極不安全的
因此我們正確的使用姿勢:是將公鑰找一個安全的地方保存起來圈纺,每次在項目啟動時動態(tài)的將公鑰設(shè)置到項目中秦忿,這樣就可以有效的保證密碼的安全了
正確的配置文件
spring:# MySQL 配置datasource:driver-class-name:com.mysql.cj.jdbc.Drivertype:com.alibaba.druid.pool.DruidDataSourcedruid:url:jdbc:mysql://127.0.0.1:3306/testdb?serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&useSSL=falseusername:root? ? ? password:IMgKm27bOHok3/+5aDL4jGBoVVZkpicbbM6pIXQppi3dI7h3jngSAqhqwqYnfuYpyVJ0k++q9xWWnHtd6sAWnQ==# encrypt configfilters:config? ? ? connect-properties:config.decrypt:trueconfig.decrypt.key:${spring.datasource.druid.publickey}
可以看出公鑰被修改成“${spring.datasource.druid.publickey}”了麦射,這就相當(dāng)于使用占位符先把坑給占上,等項目啟動時再更換上具體的值
PS:“spring.datasource.druid.publickey”并非是固定不可變的 key灯谣,此 key 值用戶可自行定義
開發(fā)環(huán)境替換公鑰
開發(fā)環(huán)境只需要在 Idea 的啟動參數(shù)中配置公鑰的值即可潜秋,如下圖所示:
當(dāng)我們輸入正確的公鑰值時程序可以正常運(yùn)行,當(dāng)輸入一個錯誤的公鑰值時就會提示解碼失敗胎许,如下圖所示:
生產(chǎn)環(huán)境替換公鑰
生產(chǎn)環(huán)境在啟動 jar 包時只需要動態(tài)設(shè)置公鑰的值即可峻呛,參考以下命令:
java -jar xxx.jar --spring.datasource.druid.publickey=你的公鑰
作者:七喜丶
鏈接:http://www.reibang.com/p/39e9ab57d167
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)辜窑,非商業(yè)轉(zhuǎn)載請注明出處钩述。