Spring項目使用Maven和BCrypt實現(xiàn)修改密碼功能方式
簡介
在數(shù)字時代,信息安全的重要性不言而喻,尤其當涉及到個人隱私和賬戶安全時。每天,無數(shù)的用戶登錄各種在線服務,從社交媒體到銀行賬戶,再到電子郵件和云存儲服務。這些服務的背后,是復雜的系統(tǒng)架構,其中包含著用戶最為敏感的數(shù)據(jù)——密碼。
過去,簡單的加密方法和弱密碼策略導致了許多嚴重的數(shù)據(jù)泄露事件。例如,2013年雅虎(Yahoo)遭遇的大規(guī)模數(shù)據(jù)泄露事件,影響了數(shù)十億的用戶賬戶,部分原因就是由于使用了不夠安全的密碼存儲技術。再如2016年的LinkedIn數(shù)據(jù)泄露事件,盡管該公司使用了SHA-1散列算法對密碼進行了處理,但未加鹽的密碼散列最終還是被破解,暴露了用戶的隱私。
這些事件引發(fā)了行業(yè)對于密碼安全的深刻反思,促使開發(fā)者和安全專家尋找更安全的解決方案。BCrypt作為一種適應性強且經(jīng)過時間考驗的密碼哈希算法,成為了現(xiàn)代密碼安全的基石。它不僅能夠有效抵御暴力破解和彩虹表攻擊,還能通過增加工作因子來適應未來計算能力的增長。
在本文中,我們將深入探討如何在Spring項目中利用Maven和BCrypt來實現(xiàn)一個安全的密碼修改功能。這不僅僅是關于代碼實現(xiàn)的問題,更是一次對密碼安全重要性的重申,以及對如何在實際應用中踐行這一原則的示范。我們將從環(huán)境搭建開始,逐步構建出一個既實用又安全的密碼修改流程,確保即使在最惡劣的情況下,用戶的密碼也能得到妥善保護。
通過本文的學習,你將獲得寶貴的實踐經(jīng)驗,了解如何在自己的項目中實施類似的解決方案,從而提升應用的安全性,給用戶提供更加安心的在線體驗。在接下來的內(nèi)容中,我們將一步步解析實現(xiàn)過程,從添加依賴到編寫核心業(yè)務邏輯,直至完成完整的功能測試,確保每一步都遵循最佳的安全實踐。
controller(UserController)
/** * 修改密碼 */ @PutMapping("/update/pwd/{id}") public Result update(@PathVariable("id") long id, @RequestBody ChangePasswordVo changePasswordVo) { try{ userService.changePassword(changePasswordVo,id); return Result.success("修改成功!"); }catch (Exception e){ // 捕獲異常,獲取異常信息 String message = e.getMessage(); // 如果修改失敗,返回失敗的結果,并附帶異常信息 return Result.failed(message); } }
1.注解 @PutMapping("/update/pwd/{id}")
@PutMapping
是Spring MVC中的一個注解,用于處理HTTP PUT請求。"/update/pwd/{id}"
是該方法的URL路徑。其中{id}
是一個路徑變量,用于接收用戶ID。
2.方法定義 public Result update(...)
- 這是一個公開的方法,名為
update
,返回一個Result
對象。 Result
很可能是一個自定義的響應類,通常用于封裝API的響應結果,包括狀態(tài)碼、消息和數(shù)據(jù)等。
3.方法參數(shù)
@PathVariable("id") long id
:這是從URL路徑中提取的id
變量。@PathVariable
注解告訴Spring MVC從URL中提取名為id
的變量值,并將其轉換為long
類型。@RequestBody ChangePasswordVo changePasswordVo
:@RequestBody
注解用于將HTTP請求體中的JSON數(shù)據(jù)轉換為ChangePasswordVo
類型的對象。ChangePasswordVo
可能是一個包含舊密碼和新密碼等信息的DTO(數(shù)據(jù)傳輸對象)。
4.方法體
- 首先,它嘗試調用
userService.changePassword(changePasswordVo,id);
。這里假設userService
是一個已經(jīng)注入的服務類,用于處理與用戶相關的業(yè)務邏輯。changePassword
方法可能會根據(jù)提供的用戶ID和密碼信息來更新用戶的密碼。 - 如果上述操作成功,方法將返回一個表示成功的
Result
對象,并附帶消息“修改成功!”。
如果在更新密碼的過程中發(fā)生異常(如數(shù)據(jù)庫錯誤、密碼驗證失敗等),catch
塊將捕獲該異常,并獲取其消息。然后,它返回一個表示失敗的Result
對象,并附帶異常的消息。
entity(VO-ChangePasswordVo)
@Data public class ChangePasswordVo implements Serializable { /** * 舊的密碼 */ private String oldpassword; /** * 新的密碼 */ private String newpassword; }
1.注解
@Data
: 這是一個Lombok庫提供的注解。當你添加@Data
到類上時,Lombok會自動為這個類生成getter、setter、equals、hashCode和toString方法。這可以大大減少模板代碼的數(shù)量,使代碼更加簡潔。implements Serializable
: 這表示該類實現(xiàn)了Serializable
接口。Serializable
是一個標記接口,用于指示一個類的對象可以被序列化。序列化是將對象狀態(tài)轉換為字節(jié)流,以便可以將其寫入文件或發(fā)送到網(wǎng)絡上的另一個位置。如果該類或其成員類(如果它們不是基本類型或String
、數(shù)組
等)需要被序列化,則必須實現(xiàn)這個接口。
2.成員變量
private String oldpassword;
: 這是一個私有字符串類型的成員變量,用于存儲舊的密碼。但是,從Java的命名約定來看,變量名應該使用駝峰命名法(camelCase),并且首字母小寫。因此,更合適的命名可能是oldPassword
。private String newpassword;
: 同樣,這是一個私有字符串類型的成員變量,用于存儲新的密碼。按照Java的命名約定,它應該被命名為newPassword
。
3.注釋
- 每個成員變量上方都有注釋,描述了該變量的用途。
- 這是一個很好的做法,因為它增加了代碼的可讀性。
- 但是,請注意,這些注釋是用中文寫的,而在國際項目中,通常建議使用英文注釋。
Service
UserService
void changePassword(ChangePasswordVo changePasswordVo, Long id);
1.返回類型 (void
): 方法前面有一個void
關鍵字,表示這個方法沒有返回值。也就是說,當你調用這個方法時,它不會返回任何值或對象。
2.方法名 (changePassword
): 這是方法的名稱,即changePassword
。當你想在代碼的其他部分調用這個方法時,你會使用這個名字。
參數(shù):
ChangePasswordVo changePasswordVo
: 這是方法的第一個參數(shù)。
ChangePasswordVo
: 這是參數(shù)的類型。它可能是一個數(shù)據(jù)傳輸對象(DTO),用于封裝與更改密碼相關的數(shù)據(jù),如舊密碼、新密碼等。changePasswordVo
: 這是參數(shù)的名稱。在方法內(nèi)部,你可以使用這個名稱來引用傳入的ChangePasswordVo
對象。
Long id
: 這是方法的第二個參數(shù)。
Long
: 這是參數(shù)的類型,表示這是一個長整型(64位整數(shù))數(shù)據(jù)。id
: 這是參數(shù)的名稱。在方法內(nèi)部,你可以使用這個名稱來引用傳入的id
值。從參數(shù)名可以推測,這個id
可能表示用戶的唯一標識符(如用戶ID)。
UserServiceImpl
@Override public void changePassword(ChangePasswordVo changePasswordVo, Long id){ // 根據(jù)id查詢用戶信息 User user = userMapper.selectById(id); // 判斷原密碼是否正確 if(!BCrypt.checkpw(changePasswordVo.getOldpassword(),user.getPassword())){ throw new RuntimeException("原密碼不正確"); } // 設置新密碼 user.setPassword(BCrypt.hashpw(changePasswordVo.getNewpassword(), BCrypt.gensalt())); // 調用Mapper的updateById方法更新用戶信息 userMapper.updateById(user); }
1.@Override:
- 這是一個Java注解,它告訴編譯器這個方法是從超類或接口中繼承或實現(xiàn)的。
- 使用
@Override
注解可以確保你正確地重寫了父類或接口中的方法,如果沒有正確重寫(例如方法簽名不匹配),編譯器會報錯。
2.public void changePassword(ChangePasswordVo changePasswordVo, Long id): 這是方法的聲明部分。
public
:表示這是一個公共方法,可以從任何其他類中被訪問。void
:表示該方法沒有返回值。changePassword
:是方法的名稱。ChangePasswordVo changePasswordVo
和Long id
:是方法的參數(shù)。ChangePasswordVo
可能是一個數(shù)據(jù)傳輸對象(DTO),用于封裝密碼更改請求所需的信息(如舊密碼和新密碼)。id
則是用戶的唯一標識符。
3.User user = userMapper.selectById(id);:
- 使用
userMapper
(可能是MyBatis的Mapper或類似的ORM工具)的selectById
方法根據(jù)提供的id
從數(shù)據(jù)庫中查詢用戶信息,并將查詢到的用戶信息存儲在user
變量中。
4.if(!BCrypt.checkpw(changePasswordVo.getOldpassword(),user.getPassword())){:
- 使用
BCrypt
庫(一個流行的密碼哈希庫)的checkpw
方法檢查用戶提供的舊密碼(從changePasswordVo
中獲?。┦欠衽c數(shù)據(jù)庫中存儲的哈希密碼(從查詢到的user
對象中獲?。┢ヅ?。 - 如果不匹配(
!BCrypt.checkpw(...)
返回true
),則執(zhí)行下面的throw
語句。
5.throw new RuntimeException("原密碼不正確");:
- 如果舊密碼不正確,則拋出一個
RuntimeException
,并帶有消息“原密碼不正確”。調用此方法的代碼應該捕獲此異常并適當?shù)靥幚硭ɡ?,向用戶顯示錯誤消息)。
6.user.setPassword(BCrypt.hashpw(changePasswordVo.getNewpassword(), BCrypt.gensalt()));:
- 如果舊密碼正確,則使用
BCrypt
庫的gensalt
方法生成一個新的隨機鹽值。 - 使用這個新鹽值和用戶提供的新密碼(從
changePasswordVo
中獲?。┳鳛閰?shù),調用BCrypt
的hashpw
方法生成新的哈希密碼。 - 將這個新的哈希密碼設置到
user
對象的password
字段中。
7.userMapper.updateById(user);:
- 使用
userMapper
的updateById
方法更新數(shù)據(jù)庫中對應id
的用戶的密碼信息。 - 這里假設
userMapper
的updateById
方法會處理將user
對象中的更改保存到數(shù)據(jù)庫中的邏輯。
測試
先新增一條數(shù)據(jù)
密碼:111
進行修改密碼;
id為你新增后的id號
輸入字段為我之前定義的字段oldpassword與newpassword
可以看到密碼已經(jīng)被修改
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
- 解決Spring security5.5.7報錯Encoded password does not look like BCrypt異常
- 使用spring?security?BCryptPasswordEncoder接入系統(tǒng)
- 如何在spring boot項目中使用Spring Security的BCryptPasswordEncoder類進行相同密碼不同密文的加密和驗證
- 一文掌握SpringSecurity?BCrypt密碼加密和解密
- Springboot基于BCrypt非對稱加密字符串的實現(xiàn)
- SpringBoot整合BCrypt實現(xiàn)密碼加密
- Spring security BCryptPasswordEncoder密碼驗證原理詳解
相關文章
Java JDK動態(tài)代理(AOP)用法及實現(xiàn)原理詳解
在本篇文章了小編給大家整理的是一篇關于Java JDK動態(tài)代理(AOP)用法及實現(xiàn)原理詳解內(nèi)容,有需要的朋友們可以參考學習下。2020-10-10Java隨手筆記8之包、環(huán)境變量和訪問控制及maven profile實現(xiàn)多環(huán)境打包
這篇文章主要介紹了Java隨手筆記8之包、環(huán)境變量和訪問控制及maven profile實現(xiàn)多環(huán)境打包的相關資料,需要的朋友可以參考下2015-11-11mybatis-plus3.0.1枚舉返回為null解決辦法
這篇文章主要介紹了mybatis-plus3.0.1枚舉返回為null解決辦法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-12-12