作者:追夢1819
原文:https://www.cnblogs.com/yanfei1819/p/15565862.html
版權宣告:本文為博主原創文章,轉載請附上博文連結!
公眾號:追夢1819
前言
專案中的配置檔案會有密碼的存在,例如資料庫的密碼、郵箱的密碼、FTP的密碼等。
配置的密碼以明文的方式暴露,並不是一種安全的方式,特別是大型專案的生產環境中,因為配置檔案經手的(運維)人員可能很多,也可能是多方的(甲方、乙方甚至第三方)。本文講述基於 SpringBoot 專案對配置檔案中的密碼進行加密。
本文例項中密碼加密主要用到的是 Jasypt,一個Java的加解密庫。
加密步驟
1、在專案中引入以下依賴。
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot</artifactId>
<version>1.18</version>
</dependency>
<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt</artifactId>
<version>1.9.2</version>
</dependency>
2、在application.yml
檔案中新增以下配置資訊。
# 配置檔案密碼加密配置
jasypt:
encryptor:
password: EbfYkitulv73I2p0mXI50JMXoaxZTKJ7 # 祕鑰
algorithm: PBEWithMD5AndDES # 加密演算法
iv-generator-classname: org.jasypt.iv.NoIvGenerator
(1)從
3.0.0jasypt-spring-boot
版本開始,預設的加密/解密演算法已更改為PBEWITHHMACSHA512ANDAES_256
;3.0.0以下版本預設為PBEWithMD5AndDES
;(2)上述
algorithm
不配置的話,其預設的祕鑰也是PBEWithMD5AndDES
;(3)以上的
jasypt.encryptor.password
並不是很多人理解的salt
(鹽),這是加密金鑰。程式碼中的salt是隨機生成的,長度預設為8位,生成類預設是org.jasypt.salt.RandomSaltGenerator
,可以通過配置jasypt.encryptor.salt-generator-classname
來修改。
3、通過命令獲取密文。
java -cp /Users/shiyanfei/zlb/repository/repository-zlb/org/jasypt/jasypt/1.9.2/jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input="Mysql@1234" password=idss@2021 algorithm=PBEWithMD5AndDES
終端執行上述命令會生成密文,其中:
/Users/shiyanfei/zlb/repository/repository-zlb/org/jasypt/jasypt/1.9.2/
是jasypt-1.9.2.jar
的路徑(Linux環境中應該是在/lib包下面),根據需求修改;- input 是明文密碼,每一個密碼都需要執行一次;
- password 是祕鑰。
4、修改原來的密碼配置
原來的明文密碼值,改為
ENC(xxx)
,其中xxx是密文。
例如:
1)MySQL
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/ueba?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&&useSSL=false
driver-class-name: com.mysql.jdbc.Driver
username: root
password: ENC(2RP1Vdsa+2wdSOgu2biAJkTCU9fnkUGD)
2)Redis
spring:
redis:
database: 0
host: 10.20.24.48
port: 6379
password: ENC(JjPTg5GOsjV9ZBIQ2CaHr+96UgMKBgIT)
5、新增註解
啟動類上新增@EnableEncryptableProperties
。
思考:以上的步驟中,根據 Jasypt 的用法,基本上完成了對配置檔案中密碼的加密。但是,請思考一下,這樣處理是否真的安全合理?
優化
如果按照嚴格的要求來,這樣處理並不是完善的。因為祕鑰和密文都暴露出來,依然是不安全的。那麼,要如何處理呢?以下是我其中的一個思路,並已在專案中實踐。
1、首先,祕鑰通過另一個小工具生成,該小工具與專案無關;
小工具是一個獨立的完整程式,有打包指令碼和啟停指令碼。篇幅所限,已將原始碼上傳至 GitHub。
2、其次,祕鑰不暴露在配置檔案中,而寫入程式碼中(正常情況下,祕鑰基本不會變動);
/************************ CHANGE REPORT HISTORY ******************************\
** Product VERSION,UPDATED BY,UPDATE DATE *
* DESCRIPTION OF CHANGE: modify(M),add(+),del(-) *
*-----------------------------------------------------------------------------*
* V3.0.12,shiyanfei,2021-09-14
* create
*
*************************** END OF CHANGE REPORT HISTORY ********************/
package com.idss.radar.common.ums.bean;
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author : shiyanfei
* @description : <p>自動配置加密資訊</p>
* @see : com.idss.radar.common.ums.bean
* @since : 2021-09-14
*/
@Configuration
public class EncryptorConfig {
@Bean("jasyptStringEncryptor")
public StringEncryptor jasyptStringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword("EbfYkitulv73I2p0mXI50JMXoaxZTKJ7");
// 註釋部分為配置預設
config.setAlgorithm("PBEWithMD5AndDES");
// config.setKeyObtentionIterations("1000");
config.setPoolSize("1");
// config.setProviderName("SunJCE");
// config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
// config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
// config.setStringOutputType("base64");
encryptor.setConfig(config);
return encryptor;
}
}
3、刪除配置檔案中的資訊
# 配置檔案密碼加密配置
jasypt:
encryptor:
password: EbfYkitulv73I2p0mXI50JMXoaxZTKJ7 # 祕鑰
algorithm: PBEWithMD5AndDES # 加密演算法
iv-generator-classname: org.jasypt.iv.NoIvGenerator
4、以上處理還有一個好處,就是優化後的專案,既支援明文,也支援密文,密文只要加函式 ENC(xxxx)
。
總結
解決問題的方案沒有最好的,只有更好的。隨著要求的不斷提高,思考的不斷深入,解決問題的方案才會逐步趨近完美。