阿里巴巴Druid,輕鬆實現MySQL數據庫鏈接加密!

爲何要加密?

如今的開發習慣,不管是公司的項目仍是我的的項目,都會選擇將源碼上傳到 Git 服務器(GitHub、Gitee 或是自建服務器),但只要將源碼提交到公網服務器就會存在源碼泄漏的風險,而數據庫配置信息做爲源碼的一部分,一旦出現源碼泄漏,那麼數據庫中的全部數據都會公之於衆,其產生的不良後果沒法預期(好比某某酒店的信息)。java

因而爲了不這種問題的產生,咱們至少要對數據庫的密碼進行加密操做,這樣即便獲得了源碼,也不會形成數據的泄露,也算保住了最後一塊遮羞布。mysql

如何加密?

對於 Java 項目來講,要想快速實現數據庫的加密,最簡單可行的方案就是使用阿里巴巴提供的 Druid 來實現加密git

什麼是Druid?

Druid(中文譯爲「德魯伊」)是阿里巴巴開源的一款 Java 語言中最好的數據庫鏈接池。Druid 提供了強大的監控和擴展功能,固然也包含了數據庫的加密功能。github

Druid 開源地址:https://github.com/alibaba/druid/spring

Druid能夠作什麼?

  1. Druid 能夠監控數據庫訪問性能,Druid 內置提供了一個功能強大的 StatFilter 插件,可以詳細統計 SQL 的執行性能,這對於線上分析數據庫訪問性能有幫助。
  2. 替換數據庫鏈接池 DBCP 和 C3P0,Druid 提供了一個高效、功能強大、可擴展性好的數據庫鏈接池。
  3. 數據庫密碼加密,直接把數據庫密碼寫在配置文件中,這是很差的行爲,容易致使安全問題。DruidDruiver 和 DruidDataSource 都支持 PasswordCallback。
  4. SQL 執行日誌,Druid 提供了不一樣的 LogFilter,可以支持 Common-Logging、Log4j 和 JdkLog,你能夠按須要選擇相應的 LogFilter,監控你應用的數據庫訪問狀況。
  5. 擴展 JDBC,若是你要對 JDBC 層有編程的需求,能夠經過 Druid 提供的 Filter-Chain 機制,很方便編寫 JDBC 層的擴展插件。

對於本文來講,咱們重點來看它的第 3 個特性,也就是使用 Druid 來實現數據庫密碼加密。sql

加密執行流程

在沒有進行密碼加密以前,項目的交互流程是這樣的:
image.png數據庫

在使用了密碼加密以後,項目的交互流程就變成了這樣:
image.png編程

使用Druid實現加密

本示例運行環境:安全

Spring Boot 2.4.3服務器

MySQL 5.7

Java 1.8

Idea 2020.1.3

1.添加Druid依賴

Maven 項目:

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid-spring-boot-starter</artifactId>
   <version>1.2.5</version>
</dependency>

Gradle 項目:

compile 'com.alibaba:druid-spring-boot-starter:1.2.5'

獲取 Druid 最新版本:https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter

2.生成密文

Druid 添加完成以後就能夠藉助 Druid 中提供的 ConfigTools 類來加密密碼了,實現代碼以下:

import com.alibaba.druid.filter.config.ConfigTools;

class MyTests {
    public static void main(String[] args) throws Exception {
        // 須要加密的明文命名
        String password = "youPassword"; // 【注意:這裏要改成你本身的密碼】
        // 調用 druid 生成私鑰、公鑰、密文
        ConfigTools.main(new String[]{password});
    }
}

以上代碼執行的結果以下:

privateKey:MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEApOjcMWSDzJiKVGmtcBBoQPtM9tVW2H2cnS6xZK7NrbzQXYWLQD2zefIrrx9vMvqRIHEqkmAHTuUcUXHgCxu0cwIDAQABAkAlqo5ItdWo0Jqf5zdXJlg5p2yP4HCiqCYyfKzF+2s9KEmgWZJWTctZDsgQ0iYUohORR59I+J4nabhel1x5/INpAiEA6jwSyFqMUPOh1XlrzNFek+RthOQ5n4+ALPo+vULayO0CIQC0O7JM9sIq+tg+jCGv+ypk6vbuRKY9m5W2rSRXapGm3wIgRHul3jAjIDPrF/f1HaAFL+Y0Yws7Ebyp8/yCRWF7iA0CIALbe20q8FMcHPeI4zPWCIsHCpkmb3hEkjAOOKhGIT8DAiAqiUuz92NqKeyjmOfons1ka65EzVwA3NDhZ6+IQcnuig==
publicKey:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKTo3DFkg8yYilRprXAQaED7TPbVVth9nJ0usWSuza280F2Fi0A9s3nyK68fbzL6kSBxKpJgB07lHFFx4AsbtHMCAwEAAQ==
password:IMgKm27bOHok3/+5aDL4jGBoVVZkpicbbM6pIXQppi3dI7h3jngSAqhqwqYnfuYpyVJ0k++q9xWWnHtd6sAWnQ==

從上述結果能夠看出,使用 ConfigTools 類會生成 3 部分的內容:

  1. privateKey:私鑰,暫時不會用到,用於密碼的加密;
  2. publicKey:公鑰,用於密碼的解密;
  3. password:加密以後的密碼。

PS:要實現數據庫的加密,主要使用的是 publicKey(公鑰)和 password(密文),這就把明文轉換成密文了。

3.添加配置

完成了以上操做以後,只須要將上一步生成的公鑰密文添加到項目的配置文件 application.yml(或application.xml)中就實現了加密操做了,具體配置信息以下:

spring:
  # MySQL 配置
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      url: jdbc:mysql://127.0.0.1:3306/testdb?serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&useSSL=false
      username: root
      password: IMgKm27bOHok3/+5aDL4jGBoVVZkpicbbM6pIXQppi3dI7h3jngSAqhqwqYnfuYpyVJ0k++q9xWWnHtd6sAWnQ==
      # encrypt config
      filters: config
      connect-properties:
        config.decrypt: true
        config.decrypt.key: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKTo3DFkg8yYilRprXAQaED7TPbVVth9nJ0usWSuza280F2Fi0A9s3nyK68fbzL6kSBxKpJgB07lHFFx4AsbtHMCAwEAAQ==

其中 password 對應的是上一步生成的 password(密文),而 config.decrypt.key 對應的是上一步生成的 publicKey(公鑰),以下圖所示:
image.png
這裏提供一個原始的配置文件,以便和加密後的配置文件進行比對:
image.png

4.注意事項-插着鑰匙的鎖

通過前面 3 步的配置以後,咱們的程序就能夠正常運行了,但這遠沒有結束!

在第 3 步配置時,咱們將密文和公鑰都寫入配置文件,這就會形成當有人拿到密文和公鑰以後,就可使用 Druid 將加密的密碼還原出來了,這就比如一把插着鑰匙的鎖是極不安全的。

所以咱們正確的使用姿式:是將公鑰找一個安全的地方保存起來,每次在項目啓動時動態的將公鑰設置到項目中,這樣就能夠有效的保證密碼的安全了。

正確的配置文件

接下來咱們將 Spring Boot 的公鑰設置爲配置項,在項目運行時再替換爲具體的值,最終的安全配置信息以下:

spring:
  # MySQL 配置
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      url: jdbc:mysql://127.0.0.1:3306/testdb?serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&useSSL=false
      username: root
      password: IMgKm27bOHok3/+5aDL4jGBoVVZkpicbbM6pIXQppi3dI7h3jngSAqhqwqYnfuYpyVJ0k++q9xWWnHtd6sAWnQ==
      # encrypt config
      filters: config
      connect-properties:
        config.decrypt: true
        config.decrypt.key: ${spring.datasource.druid.publickey}

能夠看出公鑰被修改爲「${spring.datasource.druid.publickey}」了,這就至關於使用佔位符先把坑給占上,等項目啓動時再更換上具體的值。

PS:「spring.datasource.druid.publickey」並不是是固定不可變的 key,此 key 值用戶可自行定義。

開發環境替換公鑰

開發環境只須要在 Idea 的啓動參數中配置公鑰的值便可,以下圖所示:
image.png
當咱們輸入正確的公鑰值時程序能夠正常運行,當輸入一個錯誤的公鑰值時就會提示解碼失敗,以下圖所示:
image.png

生產環境替換公鑰

生產環境在啓動 jar 包時只須要動態設置公鑰的值便可,參考如下命令:

java -jar xxx.jar --spring.datasource.druid.publickey=你的公鑰

Druid運行原理

通過上述步驟以後,咱們就完成 MySQL 密碼的加密了,這樣當 Spring Boot 項目啓動時,Druid 的攔截器會使用密文和公鑰將密碼還原成真實的密碼以供項目使用,固然這一切都無需人工干預(無需編寫任何代碼),Druid 已經幫我封裝好了,咱們只須要經過以上配置便可。

什麼?你想知道 Druid 是如何經過密文和公鑰還原出真實的密碼的?

沒問題,知足你,其實 ConfigTools 類中已經提供了相應實現,代碼以下:

// 密文
String password = "VwH1mu2IUpqjfKTd+gSikiZgJTi+3Y5zFIFRfxYnH1UqHzm1K8TIHnMaV3TErBaGsVEaGV0e63pb0Ys3Wdm7Kg==";
// 公鑰
String publicKey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALWIEp19IM04sB+vQXnEOH9gFNFdL5TFGSEhORgHj4MnfTfBSNaOoSgCaM8BOpjiHmwuEb7LpvmXI1x/ymUvNzECAwEAAQ==";
// 還原成真實的密碼
String result = ConfigTools.decrypt(publicKey, password);
System.out.println("最終結果:" + result);

總結

本文咱們使用阿里巴巴開源的 Druid 實現了 MySQL 的密碼加密,Druid 的加密過程很是方便,無需編寫任何代碼,只須要添加 Druid 依賴,再經過 Druid 的工具類生成密文,最後將密文配置到 application.yml 文件便可。項目在運行時會經過攔截器將密文轉換成真正的密碼,從而實現了 MySQL 密碼的加密和解碼的過程。

最後

原創不易,若是以爲本文對你有幫助,請點個贊再走唄。

關注公衆號「Java中文社羣」查看更多 Druid 乾貨。

相關文章
相關標籤/搜索