SpringBoot3整合SpringSecurity6添加用戶、密碼加密的方式
寫在前面
還記得在之前的文章中,我們?cè)?code>user表中手動(dòng)插入了3條數(shù)據(jù)嗎?
當(dāng)時(shí),大家就會(huì)有疑問。這一串密碼是怎么來的呢,我們?yōu)樯兑獙?duì)密碼進(jìn)行加密?
帶著這些疑問,我們繼續(xù)上路。我們?cè)陂_發(fā)一個(gè)應(yīng)用系統(tǒng),肯定是少不了用戶注冊(cè)功能的。說到注冊(cè),無非就是往user
用戶信息表中插入一條數(shù)據(jù)。
這條數(shù)據(jù)包含用戶名 [xiezhr]、密碼 [123456]等字段,而往往 密碼這個(gè)字段不可能將123456直接存儲(chǔ)的,而是通過各種加密手段處理。最終如上圖所示,
即使數(shù)據(jù)庫因各種原因泄露,法外狂徒張三也不知道用戶的密碼,這讓系統(tǒng)又加了一把鎖。
一、密碼明文存儲(chǔ)的危害
不知道大家前段時(shí)間有沒有聽到這么一個(gè)新聞。愛爾蘭數(shù)據(jù)保護(hù)委員會(huì)(DPC)對(duì)Meta(前Facebook) 處以9100萬歐元(7.14億元人民幣)的罰款,
原因正是因?yàn)镸eta在未加保護(hù)或加密的情況下以明文形式存儲(chǔ)用戶密碼。
從Meta事件再次證明了,即使在大的企業(yè),也難免會(huì)有所疏漏,雖然事件中并沒有提到泄露信息,但一旦泄露,后果真的不可想象。
密碼明文存儲(chǔ)就像是你把家里的鑰匙掛在門上,任何人都可以拿走鑰匙,進(jìn)入你的家;你的日記本沒有上鎖,任何人都可以打開看;
安全無小事,安全無小事,安全無小事。
二、加密方式及實(shí)現(xiàn)
2.1 對(duì)稱加密
① 簡(jiǎn)介
就像你和你的好朋友之間有一個(gè)只有你們倆知道的秘密暗號(hào)。你們用這個(gè)暗號(hào)來傳遞信息,別人就算看到了也看不懂。
② 常見算法
- AES(高級(jí)加密標(biāo)準(zhǔn))
- DES(數(shù)據(jù)加密標(biāo)準(zhǔn))
②實(shí)現(xiàn)
首先,你和你的朋友要商量好一個(gè)“暗號(hào)”(密鑰)。然后,你把想說的話(明文)轉(zhuǎn)換成只有你們倆能懂的暗號(hào)(密文)。你的朋友收到后,再用同樣的“暗號(hào)”把密文變回原話。
2.2 非對(duì)稱加密
① 簡(jiǎn)介
你有一個(gè)帶鎖的信箱,你把鑰匙分成兩把,一把公鑰(可以給別人),一把私鑰(自己保管)。別人用公鑰把信鎖上,只有你能用私鑰打開
② 常見算法
RSA算法
③ 實(shí)現(xiàn)
你生成一對(duì)鑰匙,公鑰和私鑰。別人用你的公鑰加密信息,然后發(fā)給你。你收到后,用自己的私鑰解密。
2.3 哈希加密
① 簡(jiǎn)介
像是把信息扔進(jìn)一個(gè)特殊的攪拌機(jī),出來的是一個(gè)固定大小的“信息指紋”。這個(gè)“指紋”不能還原成原來的信息。
② 常見算法
MD5
SHA-1
SHA-256
SHA-512
③ 實(shí)現(xiàn)
把信息(明文)通過一個(gè)哈希函數(shù)處理,生成一個(gè)哈希值。這個(gè)哈希值用來驗(yàn)證信息是否被篡改。
- 選擇一個(gè)哈希算法(如
SHA-256
)。 - 把明文通過哈希算法處理,生成哈希值。
- 存儲(chǔ)或傳輸哈希值。
- 接收者收到信息后,再次計(jì)算哈希值,與收到的哈希值對(duì)比,驗(yàn)證信息完整性。
回到Spring Sesurity
中,框架提供了PasswordEncoder
接口來實(shí)現(xiàn)密碼加密。通過不同的實(shí)現(xiàn),來配置不同Hash
算法(MD5
、SHA-256
、SHA-512
等)
但是僅僅通過上面簡(jiǎn)單的加密依然不能防止惡意用戶的攻擊,為什么呢?
惡意用戶會(huì)預(yù)先計(jì)算很多密碼的加密結(jié)果,保存到“表”里。這里的“表”指的就我們常說的彩虹表。
當(dāng)想要破解某個(gè)密碼時(shí),就會(huì)用這個(gè)密碼去“表”里查找對(duì)應(yīng)的加密結(jié)果,如果找到了,就知道這個(gè)密碼是什么了。
那么SpringSecurity
怎么才能防止彩虹表攻擊呢?
常用的就是使用鹽(Salt)
顧名思義,鹽就是給密碼加點(diǎn)“料”,每次加密時(shí)都加點(diǎn)不同的“料”,這樣即使兩個(gè)用戶的密碼相同,加密后的結(jié)果也會(huì)因?yàn)辂}的不同而不同。
Spring Security
可以通過配置密碼編碼器(如BCryptPasswordEncoder
)來自動(dòng)為每個(gè)密碼生成一個(gè)唯一的鹽來保證安全。
三、密碼加密測(cè)試
上面說了一堆理論知識(shí),接下來我們來測(cè)試下通過BCryptPasswordEncoder
來加密
@Test public void testPasswordEncoder(){ BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); //明文都是xiezhr,但是每次生成的密文是不一致的 String ret1 = encoder.encode("xiezhr"); String ret2 = encoder.encode("xiezhr"); System.out.println("第一次生成密碼:"+ret1); System.out.println("第二次生成密碼:"+ret2); Assert.isTrue(encoder.matches("xiezhr", ret1), "密碼不一致"); Assert.isTrue(encoder.matches("xiezhr", ret2), "密碼不一致"); } //輸出 第一次生成密碼:$2a$10$96WLiLGkHOcxYNw9wWHDeuXYVznW30S7F5u4Stib71gFp3Mq/mENa 第二次生成密碼:$2a$10$f1JowhAXqYI1UBF4jRY5AeziL/83NRzWfvUtxoXzgW0xUQ/uLLUWK //這里并沒有拋出密碼不一致的異常
從上面測(cè)試中,我們可以看出,相同明文"xiezhr" 通過BCrypt
算法加密后,每次生成的密文都是不同的。
再通過matches
來驗(yàn)證兩次生成的密文,都與“xiezhr” 匹配
四、添加新用戶
在前面的學(xué)習(xí)中,我們知道了怎么進(jìn)行密碼加密,接下來,該輪到實(shí)操了。
我們要實(shí)現(xiàn)將一個(gè)用戶添加到數(shù)據(jù)庫中,并且密碼進(jìn)行加密。
4.1 替換默認(rèn)密碼加密方式
在Spring Security
中默認(rèn)使用的PasswordEncoder
要求數(shù)據(jù)庫中的密碼格式為:{id}password
。它會(huì)根據(jù)id去判斷密碼的加密方式 ,所以我們之前數(shù)據(jù)庫中存儲(chǔ)的密碼為{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW
但是我們一般不會(huì)采用這種方式。所以就需要替換PasswordEncoder
默認(rèn)實(shí)現(xiàn)方式。我們一般使用SpringSecurity
為我們提供的BCryptPasswordEncoder
。
怎么替換呢?其實(shí)非常簡(jiǎn)單
我們只需要使用把BCryptPasswordEncoder
對(duì)象注入Spring
容器中,SpringSecurity
就會(huì)使用該PasswordEncoder
來進(jìn)行密碼校驗(yàn)。
@Configuration //標(biāo)明這個(gè)類為配置類,spring應(yīng)用程序一啟動(dòng),類中的been 就會(huì)被初始化在spring容器中 @EnableWebSecurity //開啟spring security 自定義配置 public class WebSecurityConfig { @Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } }
4.2 Controller
添加addUser
方法,用于接收前臺(tái)傳過來的用戶信息。這里省略了上一節(jié)的代碼
@RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @PostMapping("/addUser") public int addUser(@RequestBody User user){ return userService.addUser(user); } }
4.3 Service
由于要對(duì)前臺(tái)傳過來的密碼進(jìn)行加密處理,我們這里需要單獨(dú)添加addUser
單獨(dú)處理密碼,具體方法如下
1、UserService
public interface UserService extends IService<User> { int addUser(User user); }
2、UserServiceImpl
@Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { @Autowired PasswordEncoder passwordEncoder; @Autowired UserMapper userMapper; @Override public int addUser(User user) { String encode = passwordEncoder.encode(user.getPassword()); user.setPassword(encode); user.setEnabled(true); return userMapper.insert(user); } }
4.4 測(cè)試一下
到了這里,小伙伴是不是覺得已經(jīng)大功告成了,我們來用postman工具測(cè)試一下
哦豁,報(bào)401 Unauthorized
了,這是為啥呢?
我們要對(duì)/user/addUser
進(jìn)行放行
@Configuration //標(biāo)明這個(gè)類為配置類,spring應(yīng)用程序一啟動(dòng),類中的been 就會(huì)被初始化在spring容器中 @EnableWebSecurity //開啟spring security 自定義配置 public class WebSecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.csrf(csrf-> csrf.disable()); http.authorizeHttpRequests(auth -> auth .requestMatchers("/user/addUser").permitAll() .anyRequest().authenticated() ); return http.build(); } }
添加上面代碼之后,再用postman測(cè)試,用戶就正常添加進(jìn)去了
我們?cè)賮砜纯磾?shù)據(jù)庫,Jon這個(gè)用戶已經(jīng)加進(jìn)去了,而且密碼123456 也是加過密的
五、小結(jié)
到此,我們已經(jīng)將一個(gè)新用戶添加到數(shù)據(jù)庫中了,并且用戶密碼也做了加密處理。
以上操作,我們只是為了演示添加用戶的基本操作,實(shí)際項(xiàng)目中會(huì)比這個(gè)復(fù)雜一些,不過原理都是一樣的。
在實(shí)際的前后端分離項(xiàng)目中,我們還會(huì)涉及到跨域處理、統(tǒng)一返回結(jié)果、再插入用戶之前判斷用戶是否存在等等。
到此這篇關(guān)于SpringBoot3整合SpringSecurity6添加用戶、密碼加密的文章就介紹到這了,更多相關(guān)SpringBoot3整合SpringSecurity6添加用戶、密碼加密內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中new關(guān)鍵字和newInstance方法的區(qū)別分享
在初始化一個(gè)類,生成一個(gè)實(shí)例的時(shí)候,newInstance()方法和new關(guān)鍵字除了一個(gè)是方法一個(gè)是關(guān)鍵字外,最主要的區(qū)別是創(chuàng)建對(duì)象的方式不同2013-07-07Java多線程之并發(fā)編程的基石CAS機(jī)制詳解
這篇文章主要介紹了java并發(fā)編程之cas詳解,涉及cas使用場(chǎng)景和cas用作原子操作等內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下2021-09-09ireport數(shù)據(jù)表格報(bào)表的簡(jiǎn)單使用
這篇文章給大家介紹了如何畫一個(gè)報(bào)表模板,這里介紹下畫表格需要用到的組件,文中通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-10-10Java實(shí)現(xiàn)學(xué)生管理系統(tǒng)(IO版)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)學(xué)生管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02mybatis3.4.0不支持LocalDateTime的解決方法(No typehandler f
本文主要介紹了mybatis3.4.0不支持LocalDateTime的解決方法(No typehandler found for property time),具有一定的參考價(jià)值,感興趣的可以了解一下2025-03-03mybatis plus or and 的合并寫法實(shí)例
這篇文章主要介紹了mybatis plus or and 的合并寫法實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-02-02第三方包jintellitype實(shí)現(xiàn)Java設(shè)置全局熱鍵
本文主要介紹了,在java中使用第三方插件包jintellitype來實(shí)現(xiàn)全局熱鍵,非常的簡(jiǎn)單,但是很實(shí)用,有需要的朋友可以參考下,歡迎一起來參與改進(jìn)此項(xiàng)目2014-09-09Java實(shí)例項(xiàng)目零錢通的實(shí)現(xiàn)流程
本篇文章為你帶來Java的一個(gè)新手實(shí)戰(zhàn)項(xiàng)目,是一個(gè)零錢通系統(tǒng),項(xiàng)目來自于B站韓順平老師,非常適合新手入門練習(xí),感興趣的朋友快來看看吧2022-03-03