SpringBoot利用隨機(jī)鹽值實(shí)現(xiàn)密碼的加密與驗(yàn)證
近日,在做完博客系統(tǒng)的項(xiàng)目之后發(fā)現(xiàn)在進(jìn)行用戶登錄的時(shí)候?qū)τ诿艽a的防護(hù)性不夠嚴(yán)謹(jǐn),可能會(huì)存在密碼的安全問(wèn)題,故本文將介紹如何使用【隨機(jī)鹽值】來(lái)實(shí)現(xiàn)密碼的加密與解密
一、加密 & 代碼解讀
首先我們來(lái)看到的是第一種【加鹽加密】的方法,即為直接傳入密碼隨機(jī)產(chǎn)生鹽值來(lái)進(jìn)行加密
/**
* 加鹽加密
*
* @param password 明文密碼
* @return 加鹽加密的密碼
*/
public static String encrypt(String password) {
// 1.產(chǎn)生鹽值
String salt = UUID.randomUUID().toString().replace("-", "");
// 2.使用MD5(鹽值+明文密碼)得到加密的密碼
String finalPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
// 3.將鹽值和加密的密碼共同返回(合并鹽值和加密密碼)
String dbPassword = salt + "$" + finalPassword;
return dbPassword;
}
接下去我們來(lái)細(xì)致地解讀一下這個(gè)加鹽算法
首先我們使用工具類UUID中的randomUUID()方法,根據(jù)所傳入的兩個(gè)參數(shù)隨機(jī)產(chǎn)生一個(gè)鹽值
// 1.產(chǎn)生鹽值
String salt = UUID.randomUUID().toString().replace("-", "");
然后我們則使用工具類DigestUtils中的md5DigestAsHex()方法將隨機(jī)生成的鹽值進(jìn)行拼接然后得到最后的加密后的密碼
// 2.使用MD5(鹽值+明文密碼)得到加密的密碼 String finalPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
最后,此方法會(huì)將所得到的鹽值和最后的密碼進(jìn)行返回
// 3.將鹽值和加密的密碼共同返回(合并鹽值和加密密碼) String dbPassword = salt + "$" + finalPassword;
接下去我們?cè)賮?lái)看看另一種的加密算法,不僅是傳遞所需要加密的密碼,鹽值也需要一并地傳入
/**
* 加鹽加密
*
* @param password 明文密碼
* @param salt 可傳遞鹽值
* @return 加鹽加密的密碼
*/
public static String encrypt(String password, String salt) {
// 1.使用(鹽值+明文密碼)得到加密的密碼
String finalPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
// 2.將鹽值和加密的密碼共同返回(合并鹽值和加密密碼)
String dbPassword = salt + "$" + finalPassword;
return dbPassword;
}
??那既然已經(jīng)傳入了鹽值salt,那么除去第一步的鹽值生成,其他都是一樣的
二、驗(yàn)證 & 代碼解讀
以下是對(duì)于用戶所傳遞進(jìn)來(lái)的密碼進(jìn)行驗(yàn)證的過(guò)程
/**
* 驗(yàn)證加鹽加密密碼
*
* @param password 明文密碼(不一定對(duì),需要驗(yàn)證明文密碼)
* @param dbPassword 數(shù)據(jù)庫(kù)存儲(chǔ)的密碼(包含:salt+$+加鹽加密密碼)
* @return true=密碼正確
*/
public static boolean decrypt(String password, String dbPassword) {
boolean result = false;
if (StringUtils.hasLength(password) && StringUtils.hasLength(dbPassword) &&
dbPassword.length() == 65 && dbPassword.contains("$")) { // 參數(shù)正確
// 1.得到鹽值
String[] passwrodArr = dbPassword.split("\$");
// 1.1 鹽值
String salt = passwrodArr[0];
// // 1.2 得到正確密碼的加鹽加密密碼
// String finalPassword = passwrodArr[1];
// 2.生成驗(yàn)證密碼的加鹽加密密碼
String checkPassword = encrypt(password, salt);
if (dbPassword.equals(checkPassword)) {
result = true;
}
}
return result;
}
我們馬上來(lái)解讀一下
首先我們要先來(lái)進(jìn)行參數(shù)校驗(yàn),要檢查的就是這兩個(gè)參數(shù)是否存在,并且要檢查從數(shù)據(jù)庫(kù)中所取到的加鹽后密碼長(zhǎng)度是否== 65,而且是否包含字符“$”
if (StringUtils.hasLength(password) && StringUtils.hasLength(dbPassword) &&
dbPassword.length() == 65 && dbPassword.contains("$")) { // 參數(shù)正確
因?yàn)樗嫒霐?shù)據(jù)庫(kù)的finalPassword是salt + "$" + finalPassword;,所以我們要通過(guò)split()來(lái)取出取出和這個(gè)鹽值
// 1.得到鹽值
String[] passwrodArr = dbPassword.split("\$");
// 1.1 鹽值
String salt = passwrodArr[0];
最后,當(dāng)我們得到這個(gè)鹽值后,對(duì)用戶所傳遞進(jìn)來(lái)的密碼進(jìn)行一樣的加鹽加密,將得到后的結(jié)果與數(shù)據(jù)庫(kù)中的密碼進(jìn)行比較,如果相同的話則進(jìn)行標(biāo)記,最后我們通過(guò)result來(lái)進(jìn)行觀察
// 2.生成驗(yàn)證密碼的加鹽加密密碼
String checkPassword = encrypt(password, salt);
if (dbPassword.equals(checkPassword)) {
result = true;
}
三、測(cè)試觀察
最后我們通過(guò)實(shí)體的用戶注冊(cè)登錄來(lái)進(jìn)行一下測(cè)試,觀察是否可以達(dá)到加密與驗(yàn)證
首先看到當(dāng)前系統(tǒng)中總共有兩個(gè)用戶,分別是【admin】和【zhangsan】

然后我們?nèi)プ?cè)一個(gè)用戶名為:lisi,并且密碼為ls123的用戶

然后我們就可以看到數(shù)據(jù)庫(kù)中多了一條用戶名為:lisi,并且密碼為ls123的用戶

接著我們就可以去進(jìn)行登錄了,輸入剛才所注冊(cè)的用戶名和密碼就可以,我們一起來(lái)調(diào)試著看看

然后便很成功地登錄進(jìn)去了

我們可以再來(lái)試試輸錯(cuò)密碼的可能性。很明顯當(dāng)密碼輸錯(cuò)的時(shí)候在進(jìn)行驗(yàn)證的時(shí)候就會(huì)識(shí)別到了

以上就是SpringBoot利用隨機(jī)鹽值實(shí)現(xiàn)密碼的加密與驗(yàn)證的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot密碼加密與驗(yàn)證的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java并發(fā)編程之顯示鎖ReentrantLock和ReadWriteLock讀寫鎖
這篇文章主要介紹了Java并發(fā)編程之顯示鎖ReentrantLock和ReadWriteLock讀寫鎖,本文講解了ReentrantLock概況、Lock接口、Lock使用、輪詢鎖的和定時(shí)鎖、公平性、可中斷獲鎖獲取操作等內(nèi)容,需要的朋友可以參考下2015-04-04
SpringBoot四種讀取properties文件的方式(小結(jié))
這篇文章主要介紹了SpringBoot四種讀取properties文件的方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05
詳解備忘錄模式及其在Java設(shè)計(jì)模式編程中的實(shí)現(xiàn)
這篇文章主要介紹了詳解備忘錄模式及其在Java設(shè)計(jì)模式編程中的實(shí)現(xiàn),備忘錄模式數(shù)據(jù)的存儲(chǔ)過(guò)程中應(yīng)當(dāng)注意淺拷貝和深拷貝的問(wèn)題,需要的朋友可以參考下2016-04-04
全面詳解java代碼重構(gòu)與設(shè)計(jì)模式
這篇文章主要為大家介紹了全面詳解java代碼重構(gòu)與設(shè)計(jì)模式的全面詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06
java區(qū)分絕對(duì)路徑和相對(duì)路徑的方法
這篇文章主要介紹了java區(qū)分絕對(duì)路徑和相對(duì)路徑的方法,實(shí)例分析了java針對(duì)路徑操作的相關(guān)技巧,需要的朋友可以參考下2015-04-04
springMVC 用戶登錄權(quán)限驗(yàn)證實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了springMVC 用戶登錄權(quán)限驗(yàn)證實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
基于@RequestBody和@ResponseBody及Stringify()的作用說(shuō)明
這篇文章主要介紹了基于@RequestBody和@ResponseBody及Stringify()的作用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
Spring中的ThreadPoolTaskExecutor線程池使用詳解
這篇文章主要介紹了Spring中的ThreadPoolTaskExecutor線程池使用詳解,ThreadPoolTaskExecutor 是 Spring框架提供的一個(gè)線程池實(shí)現(xiàn),用于管理和執(zhí)行多線程任務(wù),它是TaskExecutor接口的實(shí)現(xiàn),提供了在 Spring 應(yīng)用程序中創(chuàng)建和配置線程池的便捷方式,需要的朋友可以參考下2024-01-01

