十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團隊
量身定制 + 運營維護+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
大家好,我是大澈!

成都創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),東興企業(yè)網(wǎng)站建設(shè),東興品牌網(wǎng)站建設(shè),網(wǎng)站定制,東興網(wǎng)站建設(shè)報價,網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,東興網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。
本文約3400+字,整篇閱讀大約需要6分鐘。
本文主要內(nèi)容分三部分,第一部分是需求分析,第二部分是實現(xiàn)步驟,第三部分是問題詳解。
如果您只需要解決問題,請閱讀第一、二部分即可。
如果您有更多時間,進一步學(xué)習(xí)問題相關(guān)知識點,請閱讀至第三部分。
在前端,用戶點擊登錄和注冊時,在登錄和注冊接口中不允許看到請求中真正的用戶密碼。
在后端,用戶點擊登錄和注冊時,在數(shù)據(jù)庫中不允許存取真正的用戶密碼。
在學(xué)習(xí)如何使用之前,我們要明白的是,在項目中如果進行密碼加密,有哪幾種情況。然后就是,實現(xiàn)密碼加密的方式有哪些,哪一種是相較來說,較好用及安全性較高的。
密碼加密實現(xiàn)情況:
已上這三種情況,在實際的開發(fā)中,使用較多的,當(dāng)然是第一種情況,這種情況可以提供更高的安全性和密碼保護。
前端將用戶密碼進行加密后再傳輸給后端,可以減少密碼在網(wǎng)絡(luò)傳輸過程中的風(fēng)險,確保密碼的機密性。
后端再對接收到的密碼進行加密,將加密后的密碼存儲到數(shù)據(jù)庫中。這樣即使數(shù)據(jù)庫遭到非法訪問,密碼也不會以明文形式暴露,增加了密碼的安全性。
這一點說明到這里打住,不再贅述。
然后就是實現(xiàn)密碼加密的常用方式:
對稱加密算法使用相同密鑰進行加密和解密,非對稱加密算法使用公鑰和私鑰,哈希函數(shù)將數(shù)據(jù)轉(zhuǎn)換為固定長度的哈希值,密碼推導(dǎo)函數(shù)通過迭代和加鹽增加密碼破解難度。
上述加密方式,從上往下,安全性依次增高。
這一點在這里只做簡要說明,有需要的朋友,請見第三部分對加密方式的詳細總結(jié)。
搞清楚這些,然后下面,就是如何使用的問題了。
為提高大家的使用效率,這里大澈只提供較常用的情況(第一種),以及較安全的密碼加密方式(BCrypt)的使用。
其它加密方式的使用,與此大同小異。
模板代碼:
引入依賴:
npm i bcryptjs邏輯代碼:
這里做一下說明:
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@RestController
public class UserController {
// 設(shè)置與前端相同的 cost 鹽值
private static final int COST = 10;
@Autowired
private PasswordEncoder passwordEncoder;
// 注冊接口
@PostMapping("/register")
public ResponseEntity> registerUser(@RequestBody UserRequest userRequest) {
String username = userRequest.getUsername();
String password = userRequest.getPassword(); // 前端已經(jīng)進行了密碼加密
// 后端對密碼進行加密
String encryptedPassword = passwordEncoder.encode(password);
// 存儲用戶信息及加密后的密碼、對應(yīng)鹽值到數(shù)據(jù)庫
// ...
return ResponseEntity.ok("User registered successfully!");
}
// 登錄接口
@PostMapping("/login")
public ResponseEntity> loginUser(@RequestBody UserRequest userRequest) {
String username = userRequest.getUsername();
String password = userRequest.getPassword(); // 前端已經(jīng)進行了密碼加密
// 從數(shù)據(jù)庫中根據(jù)用戶名查詢用戶信息
User user = userRepository.findByUsername(username);
if (user == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid username or password");
}
// 后端驗證密碼
boolean isMatched = passwordEncoder.matches(password, user.getPassword());
// 認證成功,生成 JWT Token 等操作
// ...
if (isMatched) {
return ResponseEntity.ok("Login successful!");
} else {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid username or password");
}
}
}AES:
RSA:
MD5:
SHA:
BCrypt:
PBKDF2:
SCrypt:
很枯燥的一段學(xué)術(shù)語言,大家隨便看看即可,哈哈哈。
這里也是為什么使用MD5加密時,常常會進行加鹽處理的原因了。
在密碼學(xué)中,不可逆(irreversible)表示無法從哈希值還原出原始數(shù)據(jù)。
當(dāng)數(shù)據(jù)經(jīng)過哈希函數(shù)處理后,生成的哈希值是固定長度的一串字符。不可逆意味著無法通過逆向計算或解密操作來獲取原始數(shù)據(jù)。即使輸入數(shù)據(jù)的細微改變也會導(dǎo)致生成完全不同的哈希值。
這種不可逆性是哈希函數(shù)的重要特性之一,用于保證數(shù)據(jù)的完整性和驗證數(shù)據(jù)的一致性。通過對原始數(shù)據(jù)進行哈希處理,并將哈希值與預(yù)期的哈希值進行比對,可以快速檢查數(shù)據(jù)是否被篡改或損壞。如果哈希值相同,則可以確定數(shù)據(jù)完整性沒有受到破壞;如果哈希值不同,則說明數(shù)據(jù)已被修改,或者數(shù)據(jù)傳輸過程中出現(xiàn)了錯誤。
需要注意的是,雖然哈希函數(shù)是不可逆的,但是存在哈希碰撞的概率,即不同的輸入數(shù)據(jù)可能會產(chǎn)生相同的哈希值。然而,好的哈希函數(shù)應(yīng)該具有極低的碰撞概率,以確保數(shù)據(jù)完整性和安全性。
Base64編碼只是一種編碼傳輸方式,不是加密算法。
它將二進制數(shù)據(jù)轉(zhuǎn)換為可打印的ASCII字符,常用于在文本協(xié)議中傳輸或存儲二進制數(shù)據(jù),例如在電子郵件中傳輸附件、在網(wǎng)頁中嵌入圖像等。
我們常常會將Base64誤解為它是一種加密方式,其實不然,Base64和我們常用的JWT一樣,都是一種數(shù)據(jù)編碼傳輸方式,只不過Base64常用于在文本環(huán)境中傳輸圖片、文件。
以下是常用應(yīng)用場景的詳細說明:
雖然Base64有以上作用,但它會導(dǎo)致數(shù)據(jù)膨脹,增加數(shù)據(jù)的大小。
在傳輸大量二進制數(shù)據(jù)或?qū)鬏斝视休^高要求的情況下,如傳輸大視頻、大圖片、大文件等,不易使用。
如果需要在文本環(huán)境中傳輸大文件,可以考慮使用其他更合適的技術(shù),例如使用壓縮算法對文件進行壓縮,或者使用分布式文件系統(tǒng)或云存儲服務(wù),如Minio、OSS,來處理大文件的傳輸和存儲。