SpringBoot敏感配置加密:Druid

背景

  • 對於配置中的密碼(DB, MQ, Redis等),甚至賬號,在生產環境下存明文,不安全,不專業,不合適。

  • 一把插着鑰匙的鎖,能說它是安全的嗎?

操作流程

Druid本身提供了加密功能,關於Druid實現對配置項的加密,網絡上已經有很多這方面的資料,這裏簡要描述下步驟。

  1. 生成密鑰與密文
  • 如果計算機上有項目用過druid的,那麼在maven的倉庫目錄下會有druid的jar包。

2020-05-22-druid-path.png

  • 在此打開cmd命令行,鍵入java -cp .\druid-1.1.21.jar com.alibaba.druid.filter.config.ConfigTools root > generated.txt

2020-05-22-druid-encrypt.png這裏生成的publicKeypassword在接下來要放入配置文件。

  1. 修改已有的配置

在已有的明文配置文件中,修改druid密碼相關配置。

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    druid:
      url: jdbc:mysql://localhost:3306/boost-admin?serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&useSSL=false
      username: root
      password: D/pBfX7uKgNrFNtVbvf5pevX5JAcBbzisC/4JK3hTN5Xty3sm8zWtSjd9TwggT/phP8Ob0wg1qZRVolxmd/39g==
      # encrypt config
      filters: config
      connect-properties:
        config.decrypt: true
        config.decrypt.key: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIYYdcdptMU6n/4wtb7StmX4LFvmlw7+b5KHm7L8C0txn1+iMeXz3FM7emkGkKMuaLd9OazkjgxNpPCDRaNM7ecCAwEAAQ==

mybatis:
  mapperLocations: classpath:mapper/*.xml
  typeAliasesPackage: com.heartsuit.springbootmybatis.oa.entity
  configuration:
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

上面的修改主要有:
2020-05-22-druid-config.png3. 測試修改後的配置

略(按照上述配置,應一切正常~~)

Note: 需要注意的是,druid是用私鑰加密,公鑰解密的,即如果公鑰爲所有人可見,那麼所有人均可以解密。因此,上述配置若在團隊內可見,沒什麼影響,但是如果配置文件萬一被放到了公網上,相當於把鑰匙插在鎖上,白加密了。。在生產環境下,建議改爲如下配置:

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    druid:
      url: jdbc:mysql://localhost:3306/boost-admin?serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&useSSL=false
      username: root
      password: D/pBfX7uKgNrFNtVbvf5pevX5JAcBbzisC/4JK3hTN5Xty3sm8zWtSjd9TwggT/phP8Ob0wg1qZRVolxmd/39g==
      # encrypt config
      filters: config
      connect-properties:
        config.decrypt: true
        config.decrypt.key: ${spring.datasource.druid.publickey}

mybatis:
  mapperLocations: classpath:mapper/*.xml
  typeAliasesPackage: com.heartsuit.springbootmybatis.oa.entity
  configuration:
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

一行之差:config.decrypt.key: ${spring.datasource.druid.publickey},這裏${spring.datasource.druid.publickey}可以有兩種傳入方式:

  • 通過服務啓動參數
java -jar xxx.jar --spring.datasource.druid.publickey=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIYYdcdptMU6n/4wtb7StmX4LFvmlw7+b5KHm7L8C0txn1+iMeXz3FM7emkGkKMuaLd9OazkjgxNpPCDRaNM7ecCAwEAAQ==
  • 通過系統環境變量

這個可以通過Idea IDE傳入(開發環境),或者實際的系統環境變量傳入(生產環境)。

Druid的加密與解密

通過druid命令行的方式生產密文密碼後,可以用druid提供的API進行解密,當然,也可以用API的方式來完成加密。

  1. 加密
public void encrypt() throws Exception {
    String password = "root";
    String[] keyPair = ConfigTools.genKeyPair(512);
    String privateKey = keyPair[0];
    String publicKey = keyPair[1];
    System.out.println("私    鑰: " + privateKey);
    System.out.println("公    鑰: " + publicKey);
    String encryptPassword = ConfigTools.encrypt(privateKey, password);
    System.out.println("密文密碼: " + encryptPassword);

    /** 輸出:
        * 私    鑰: MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmsdCBWKd4FRoGJ0+PMtIepI8LWAHd3TysWGKOlfvF8UtXqOv8agodlQ4jcbPH6JoVRcEkgpqteWhj/v7vwc61QIDAQABAkB5ockCTmNfHTXI0hlM0TueBzl/Nw3nFGJ8fviPrPbZqAM6OTZNuA8Uka7AAU5MpbwYbrNcRjXqT5RzaicNrOPBAiEA0BuYwQmRzYLY27xkY99BfLQqwUimR3kwowBUHToV3/0CIQC+ZdNJ71zTW5WDARUz8B8vOBZYfJx25qrCzHbL3DfhuQIhAMwyF9tpeV/uQLyzCMoaONaUrdMDZuyAlGGMI/ydjvM9AiBb650OXNlb0SNlk+hAovTrPxDKt55yaPqYAU55LWBtQQIgYsLxtClktL+ZgVQkGL7Rqa44E7L1TYHl8zyBSbaeYiQ=
        * 公    鑰: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJrHQgVineBUaBidPjzLSHqSPC1gB3d08rFhijpX7xfFLV6jr/GoKHZUOI3Gzx+iaFUXBJIKarXloY/7+78HOtUCAwEAAQ==
        * 密文密碼: VFDsVA2tKIonKgNtPHadtBljYkuA1K6PnW8hTy1ZzADbRldd280Z/nbHv5TW9J7JZyK/q411Sg1GE4elxKoYcQ==
        * */
}
  1. 解密
public void decrypt() throws Exception {
    String encrypted = "VFDsVA2tKIonKgNtPHadtBljYkuA1K6PnW8hTy1ZzADbRldd280Z/nbHv5TW9J7JZyK/q411Sg1GE4elxKoYcQ==";
    String publicKey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJrHQgVineBUaBidPjzLSHqSPC1gB3d08rFhijpX7xfFLV6jr/GoKHZUOI3Gzx+iaFUXBJIKarXloY/7+78HOtUCAwEAAQ==";

    String decrypted = ConfigTools.decrypt(publicKey, encrypted);
    System.out.println("解密之後:" + decrypted);
    /** 輸出:
    * 解密之後:root
    * */
}

總結

實現對配置文件敏感數據的加密,網上資源很多,但一定要注意安全性,不可以把公鑰共開配置在文件中;還是開頭那句話:

一把插着鑰匙的鎖,能說它是安全的嗎?

Source Code: Github


If you have any questions or any bugs are found, please feel free to contact me.

Your comments and suggestions are welcome!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章