springboot配置文件加密

先看一份典型的配置文件

...?省略?...

##?配置MySQL數(shù)據(jù)庫連接

spring.datasource.driver-class-name=com.mysql.jdbc.Driver

spring.datasource.url=jdbc:mysql://121.196.xxx.xxx:3306/user?useUnicode=true&characterEncoding=utf-8

spring.datasource.username=root

spring.datasource.password=123456

##?配置Redis緩存連接

redis.host=121.196.xxx.xxx

redis.port=6379

redis.password=111111

##?配置SMS短信服務(wù)連接

ali.sms.access_key_id=2zHmLdxAes7Bbe2w

ali.sms.access_key_secret=bImWdv6iy0him8ly

...?省略?...

這是節(jié)選自某個典型的Spring Boot項目的application.properties配置文件。

這乍一看沒啥問題丐怯,很多人會覺得理所當(dāng)然笆载。包括我自己也看到過很多的項目(包括很多開源項目)是這么寫的。

但仔細一琢磨,發(fā)現(xiàn):

是的!很多項目的配置文件里,包括數(shù)據(jù)庫密碼泛粹、緩存密碼、亦或是一些第三方服務(wù)的Key都是直接配在里面肮疗,沒有做任何加密處理晶姊!

有人會說這個配置文件反正是我自己的,有啥風(fēng)險伪货?

這個嘛们衙,之前倒是看到過一個例子,一個程序員把自己公司的項目代碼上傳到了自己的GitHub倉庫里了碱呼,結(jié)果配置文件忘了處理蒙挑,導(dǎo)致公司數(shù)據(jù)庫泄露...

換個角度想,假如當(dāng)時那個項目的配置文件里巍举,所有重要信息都經(jīng)過了加密脆荷,那這一幕大概率就不會發(fā)生了。所以懊悯,即使是項目的配置文件,重要的信息也得加密梦皮!

哪些信息要加密呢炭分?

一般來說,項目配置文件里剑肯,所有涉及信息安全的配置項(或字段)都應(yīng)該做處理捧毛,典型的比如:

用到的數(shù)據(jù)庫、緩存的密碼

用到的中間件、消息隊列的密碼

用到的各種第三方服務(wù)的Access_Key

其他第三方服務(wù)的通信信息

......等等

總而言之呀忧,關(guān)鍵字段都應(yīng)該保護起來师痕,最起碼不能用明文直接寫在配置文件里!

如何加密配置項呢而账?

方法非常簡單胰坟,幾個步驟即可完成,先來演示一個最簡版本:

1泞辐、首先建立一個基礎(chǔ)的Spring Boot工程

這就不再贅述了

2笔横、引入jasypt-spring-boot加密組件

通過jasypt-spring-boot這個開箱即用的加密組件來引入Jasypt這個強大的加密庫

com.github.ulisesbocchio

jasypt-spring-boot-starter

3.0.2

3、配置加密密鑰

在Spring Boot的項目配置文件application.properties里新增如下配置:

jasypt.encryptor.password=CodeSheep

可以理解為jasypt會使用這個自定義加密密鑰咐吼,對配置文件里的重要項進行加密吹缔。

4、加密測試

為了便于測試锯茄,我們直接擴展Spring Boot項目的啟動類厢塘,項目啟動時執(zhí)行加密測試代碼,直接看效果

@SpringBootApplication

publicclassSpringBootConfigEncryptApplicationimplementsCommandLineRunner{

@Autowired

privateApplicationContext?appCtx;

@Autowired

privateStringEncryptor?codeSheepEncryptorBean;

publicstaticvoidmain(String[]?args){

SpringApplication.run(SpringBootConfigEncryptApplication.class,args);

}

@Override

publicvoidrun(String...?args)throwsException{

Environment?environment?=?appCtx.getBean(Environment.class);

//?首先獲取配置文件里的原始明文信息

String?mysqlOriginPswd?=?environment.getProperty("spring.datasource.password");

String?redisOriginPswd?=?environment.getProperty("redis.password");

String?aliSmsOriginAk?=?environment.getProperty("ali.sms.access_key_secret");

//?加密

String?mysqlEncryptedPswd?=?encrypt(?mysqlOriginPswd?);

String?redisEncryptedPswd?=?encrypt(?redisOriginPswd?);

String?aliSmsEncryptedAk?=?encrypt(?aliSmsOriginAk?);

//?打印加密前后的結(jié)果對比

System.out.println("MySQL原始明文密碼為:"+?mysqlOriginPswd?);

System.out.println("Redis原始明文密碼為:"+?redisOriginPswd?);

System.out.println("阿里云SMS原始AccessKey密碼為:"+?aliSmsOriginAk?);

System.out.println("====================================");

System.out.println("MySQL原始明文密碼加密后的結(jié)果為:"+?mysqlEncryptedPswd?);

System.out.println("Redis原始明文密碼加密后的結(jié)果為:"+?redisEncryptedPswd?);

System.out.println("阿里云SMS原始AccessKey密碼加密后的結(jié)果為:"+?aliSmsEncryptedAk?);

}

privateStringencrypt(?String?originPassord?){

String?encryptStr?=?codeSheepEncryptorBean.encrypt(?originPassord?);

returnencryptStr;

}

privateStringdecrypt(?String?encryptedPassword?){

String?decryptStr?=?codeSheepEncryptorBean.decrypt(?encryptedPassword?);

returndecryptStr;

}

}

運行項目肌幽,控制臺打铀锥场:

MySQL原始明文密碼為:123456

Redis原始明文密碼為:111111

阿里云SMS原始AccessKey密碼為:bImWdv13da894mly

====================================

MySQL原始明文密碼加密后的結(jié)果為:IV7SyeQOfG4GhiXeGLboVgOLPDO+dJMDoOdmEOQp3KyVjruI+dKKeehsTriWPKbo

Redis原始明文密碼加密后的結(jié)果為:litUkxJ3fN6+//Emq3vZ+y4o7ZOnZ8doOy7NrgJIDLoNWGG0m3ygGeQh/dEroKvv

阿里云SMS原始AccessKey密碼加密后的結(jié)果為:MAhrOs20DY0RU/c1IKyLCt6dWZqLLOO4wUcK9GBgSxNII3C+y+SRptors+FyNz55xNDslhDnpWllhcYPwZsO5A==

5、修改配置文件牍颈,替換待加密配置項

我們拿到上一步得到的加密結(jié)果迄薄,將配置文件中的原始明文密碼替換成上一步對應(yīng)的結(jié)果即可,就像這樣:

所以墻裂建議配置文件里的所有重要信息都這樣處理煮岁!

6讥蔽、查看密碼解密結(jié)果

@SpringBootApplication

publicclassSpringBootConfigEncryptApplicationimplementsCommandLineRunner{

@Autowired

privateApplicationContext?appCtx;

@Autowired

privateStringEncryptor?codeSheepEncryptorBean;

publicstaticvoidmain(String[]?args){

SpringApplication.run(SpringBootConfigEncryptApplication.class,args);

}

@Override

publicvoidrun(String...?args)throwsException{

Environment?environment?=?appCtx.getBean(Environment.class);

//?首先獲取配置文件里的配置項

String?mysqlOriginPswd?=?environment.getProperty("spring.datasource.password");

String?redisOriginPswd?=?environment.getProperty("redis.password");

String?aliSmsOriginAk?=?environment.getProperty("ali.sms.access_key_secret");

//?打印解密后的結(jié)果

System.out.println("MySQL原始明文密碼為:"+?mysqlOriginPswd?);

System.out.println("Redis原始明文密碼為:"+?redisOriginPswd?);

System.out.println("阿里云SMS原始AccessKey密碼為:"+?aliSmsOriginAk?);

}

}

打印結(jié)果:

MySQL原始明文密碼為:123456

Redis原始明文密碼為:111111

阿里云SMS原始AccessKey密碼為:bImWdv13da894mly

很明顯,在代碼中使用時画机,jasypt-spring-boot組件會自動將ENC()語法包裹的配置項加密字段自動解密冶伞,數(shù)據(jù)得以還原。

幾個問題

1步氏、加密密鑰必須放在ENC()中响禽?為什么是ENC?

2荚醒、雖然說原始涉及信息安全的配置項被加密芋类,但是自定義的加密密鑰jasypt.encryptor.password=CodeSheep假如泄露了,別人不還是有幾率可以解密的嗎界阁?

針對這些問題侯繁,繼續(xù)往下看。

自定義加密前后綴

如果不愿意使用jasypt默認提供的ENC來標(biāo)記加密字段泡躯,完全可以換成自定義的前后綴標(biāo)記贮竟,比如我想換成CodeSheep()來標(biāo)記加密字段丽焊,此時只需要在配置文件里配置一下前后綴即可:

jasypt.encryptor.property.prefix=CodeSheep(

jasypt.encryptor.property.suffix=)

這時候加密字段就可以放在CodeSheep()標(biāo)記的字段中:

讓加密更安全

雖然經(jīng)過上文的加密,涉及信息安全的配置項肯定會變得更安全咕别,這個毋庸置疑技健!

但是假如配置文件里的自定義加密密鑰jasypt.encryptor.password=CodeSheep泄露了,那我們的加密字段也還是有可能被別人解密惰拱,為此雌贱,有幾項工作可以讓加密變得更加安全。

1弓颈、使用自定義加密器

上文實驗加密時帽芽,使用的是默認的加密規(guī)則,這一點會讓當(dāng)自定義加密密鑰泄漏時可能變得不安全翔冀。為此我們可以自定義加密規(guī)則导街。

自定義加密規(guī)則非常簡單,只需要提供自定義的加密器配置類即可纤子,比如我這里自定義一個名為codeSheepEncryptorBean類型的加密器:

@Configuration

publicclassCodeSheepEncryptorCfg{

@Bean(?name?="codeSheepEncryptorBean")

publicStringEncryptorcodesheepStringEncryptor(){

PooledPBEStringEncryptor?encryptor?=newPooledPBEStringEncryptor();

SimpleStringPBEConfig?config?=newSimpleStringPBEConfig();

config.setPassword("CodeSheep");

config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");

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);

returnencryptor;

}

}

注意這里Bean的名字name是需要顯式指定的(默認的名字是jasyptStringEncryptor)搬瑰,如果像這里一樣用的自定義名字,則還需要在Spring Boot的application.properties配置文件中來指定bean的名字控硼,就像這樣:

jasypt.encryptor.bean=codeSheepEncryptorBean

2泽论、加密密鑰不要寫在配置文件中

如果覺得上面這種方式還是可能會導(dǎo)致加密密鑰泄露的話(畢竟還是寫在了配置文件中),那我們干脆可以直接將加密密鑰從配置文件中拿掉卡乾,取而代之的有三種方式

方式一:直接作為程序啟動時的命令行參數(shù)來帶入

java?-jar?yourproject.jar?--jasypt.encryptor.password=CodeSheep

方式二:直接作為程序啟動時的應(yīng)用環(huán)境變量來帶入

java?-Djasypt.encryptor.password=CodeSheep?-jar?yourproject.jar

方式三:甚至可以作為系統(tǒng)環(huán)境變量的方式來帶入

比方說翼悴,我們提前設(shè)置好系統(tǒng)環(huán)境變量JASYPT_ENCRYPTOR_PASSWORD = CodeSheep,則直接在Spring Boot的項目配置文件中做如下配置即可:

jasypt.encryptor.password=${JASYPT_ENCRYPTOR_PASSWORD:}

這時候也會安全得多幔妨。

原創(chuàng) @CodeSheep?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鹦赎,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子误堡,更是在濱河造成了極大的恐慌古话,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锁施,死亡現(xiàn)場離奇詭異陪踩,居然都是意外死亡,警方通過查閱死者的電腦和手機悉抵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門肩狂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人基跑,你說我怎么就攤上這事婚温。” “怎么了媳否?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵栅螟,是天一觀的道長。 經(jīng)常有香客問我篱竭,道長力图,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任掺逼,我火速辦了婚禮吃媒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吕喘。我一直安慰自己赘那,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布氯质。 她就那樣靜靜地躺著募舟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪闻察。 梳的紋絲不亂的頭發(fā)上拱礁,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機與錄音辕漂,去河邊找鬼呢灶。 笑死,一個胖子當(dāng)著我的面吹牛钉嘹,可吹牛的內(nèi)容都是我干的鸯乃。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼跋涣,長吁一口氣:“原來是場噩夢啊……” “哼缨睡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起仆潮,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤宏蛉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后性置,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拾并,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年鹏浅,在試婚紗的時候發(fā)現(xiàn)自己被綠了嗅义。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡隐砸,死狀恐怖之碗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情季希,我是刑警寧澤褪那,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布幽纷,位于F島的核電站,受9級特大地震影響博敬,放射性物質(zhì)發(fā)生泄漏友浸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一偏窝、第九天 我趴在偏房一處隱蔽的房頂上張望收恢。 院中可真熱鬧,春花似錦祭往、人聲如沸伦意。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽驮肉。三九已至,卻和暖如春括勺,著一層夾襖步出監(jiān)牢的瞬間缆八,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工疾捍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留奈辰,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓乱豆,卻偏偏與公主長得像奖恰,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子宛裕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容