Spring security實(shí)現(xiàn)對(duì)賬戶進(jìn)行加密
一、原理分析1.1加密原理
首先前端頁(yè)面發(fā)送注冊(cè)的賬戶信息到controller層,然后依次經(jīng)過service層和dao層,最后入庫(kù)。其中對(duì)密碼的加密應(yīng)該放在service層進(jìn)行,加密后再入庫(kù)。
spring security中有一個(gè)加密類BCryptPasswordEncoder可以用來(lái)對(duì)密碼進(jìn)行加密,調(diào)用其中的encode方法返回一個(gè)加密后的字符串
public String encode(CharSequence rawPassword) { String salt; if (strength > 0) { if (random != null) {salt = BCrypt.gensalt(strength, random); } else {salt = BCrypt.gensalt(strength); } } else { salt = BCrypt.gensalt(); } return BCrypt.hashpw(rawPassword.toString(), salt);}
使用時(shí)可以在spring的配置文件中配置一個(gè)加密類的bean,這樣在service中可以直接注入
加密后數(shù)據(jù)庫(kù)中存儲(chǔ)的是加密過后的字符串。
1.2加密后的登錄過程
對(duì)密碼進(jìn)行加密后數(shù)據(jù)庫(kù)中存儲(chǔ)的是加密字符串,用戶發(fā)起登錄請(qǐng)求后,框架會(huì)使用相同的加密算法對(duì)前端傳遞的密碼進(jìn)行加密并得到加密字符串,然后和數(shù)據(jù)庫(kù)中查詢到的字符串進(jìn)行對(duì)比。
二、代碼實(shí)現(xiàn)
具體的工程代碼可以參考我的工程示例,下文中只給出了和添加用戶相關(guān)的部分。
在配置文件中配置加密類
<bean class='org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder'> </bean>
2.1添加用戶的頁(yè)面如下, register.html
<html> <head> <meta charset='UTF-8'> <title>注冊(cè)頁(yè)面</title> </head> <body> <form action='/user/add.do' method='post'> 用戶名:<input type='text' name='username' placeholder='請(qǐng)輸入用戶名'><br> 密 碼:<input type='password' name='password' placeholder='請(qǐng)輸入密碼'><br> <input type='submit' value='注冊(cè)'> </form> </body></html>
2.2controller層創(chuàng)建一個(gè)增加用戶的方法
@RestController@RequestMapping('/user')public class UserController { @Autowired private IUserService userService; @PostMapping('/add') public String add(UserInfo userInfo){ userService.add(userInfo); return 'success'; }}
2.3service層
@Autowiredprivate BCryptPasswordEncoder passwordEncoder;...//省略其他@Overridepublic void add(UserInfo userInfo) { //對(duì)密碼加密 userInfo.setPassword(passwordEncoder.encode(userInfo.getPassword())); userDao.add(userInfo);}
這里的passwordEncoder就是在配置文件中配置的加密bean,注入后可以直接使用
dao層這里就不再列舉了。
三、測(cè)試
啟動(dòng)工程并成功登錄后,跳轉(zhuǎn)到首頁(yè),
選擇注冊(cè)新賬號(hào)后跳轉(zhuǎn)到注冊(cè)頁(yè)面
輸入賬戶和密碼后注冊(cè),會(huì)在數(shù)據(jù)庫(kù)中插入一條新的記錄。
這里我頁(yè)面上輸入的是 admin/admin,數(shù)據(jù)庫(kù)中存儲(chǔ)的password是加密后的
$2a$10$URSaaafrPOCjFYvhrhQbku2/l36IJ0zH0G8xeJzf5lAH2F1JJ1ybG
四、用加密后的賬號(hào)登錄
此時(shí)如果使用剛剛新建的這個(gè)賬號(hào)進(jìn)行登錄就會(huì)登錄失敗。因?yàn)槲覀儾]有配置spring security認(rèn)證時(shí)的加密方式,默認(rèn)是不進(jìn)行加密,所以會(huì)直接將前臺(tái)輸入的密碼和數(shù)據(jù)庫(kù)中的加密字符串進(jìn)行比較。
要使用這個(gè)賬號(hào)登錄還需要進(jìn)行如下配置
在spring security的配置文件中配置加密策略
<security:authentication-manager> <!--配置使用給定的userservice完成認(rèn)證--> <security:authentication-provider user-service-ref='userService'> <security:password-encoder ref='passwordEncoder'/> </security:authentication-provider> </security:authentication-manager> <bean class='org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder'> </bean>
在userService的loadUserByUsername方法中去除密碼字符串上拼接的{noop}字符串,本來(lái)這個(gè)就是為了適配密碼未加密的情況
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { UserInfo userInfo = userDao.findByUsername(username); User user=new User(userInfo.getUsername(),userInfo.getPassword(),getRoles()); return user;}
然后使用剛才注冊(cè)的 admin/admin就可以登錄成功了。
注意如果進(jìn)行了上面兩部,數(shù)據(jù)庫(kù)中以前的賬戶將不能進(jìn)行登錄了,因?yàn)閿?shù)據(jù)庫(kù)中的密碼是沒有加密的,而框架會(huì)對(duì)前臺(tái)傳遞的密碼進(jìn)行加密后再和數(shù)據(jù)庫(kù)中的比較。所以一定要記住上面新注冊(cè)的這個(gè)賬號(hào)admin/admin
這里我給出admin對(duì)應(yīng)的加密字符串
$2a$10$URSaaafrPOCjFYvhrhQbku2/l36IJ0zH0G8xeJzf5lAH2F1JJ1ybG
如果大家忘記了剛才注冊(cè)的賬號(hào),可以在數(shù)據(jù)庫(kù)中插入一條admin/admin的記錄。
五、總結(jié)
添加賬戶主要是需要用spring security自帶的加密類BCryptPasswordEncoder對(duì)用戶密碼進(jìn)行加密。
要使用新注冊(cè)的賬戶登錄就需要在配置文件中配置加密策略
配置后原來(lái)的賬號(hào)因?yàn)槊艽a沒有加密將不能使用
六、示例工程源碼
示例工程已經(jīng)上傳到碼云上,如果有需要?dú)g迎大家參考
示例工程
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. IntelliJ IDEA導(dǎo)入jar包的方法2. SSM框架JSP使用Layui實(shí)現(xiàn)layer彈出層效果3. 刪除docker里建立容器的操作方法4. IntelliJ IDEA導(dǎo)出項(xiàng)目的方法5. 簡(jiǎn)單了解Python字典copy與賦值的區(qū)別6. Java源碼解析之ClassLoader7. Python如何測(cè)試stdout輸出8. Java導(dǎo)出Execl疑難點(diǎn)處理的實(shí)現(xiàn)9. 解決python DataFrame 打印結(jié)果不換行問題10. .Net中的Http請(qǐng)求調(diào)用詳解(Post與Get)
