在前一節使用數據庫進行用戶認證(form login using database)里,我們學習了如何把“登錄帳號、密碼”存儲在db中,但是密碼都是明文存儲的,顯然不太講究。這一節將學習如何使用spring security3新加入的bcrypt算法,將登錄加密存儲到db中,並正常通過驗證。
一、Bcrypt算法
int t = 0; String password = "123456"; System.out.println(password + " -> "); for (t = 1; t <= 10; t++) { BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); String hashedPassword = passwordEncoder.encode(password); System.out.println(hashedPassword); } password = "MIKE123"; System.out.println(password + " -> "); for (t = 1; t <= 10; t++) { BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); String hashedPassword = passwordEncoder.encode(password); System.out.println(hashedPassword); }
輸出如下:
123456 -> 2a10$.Cjkvbgr2JzGkag9IdbT.Oc/sbY7wVqLgAHws7HCxqcI7eczKtCLq 2a10$OCOuRV0Wy7ncCND4LcKfMunVEWOzMOyyU95u5TkTRmJqYbsJNecEK 2a10$TXttsDZUaeEb2zX6wiwN0eqREKFoCDyh81Kfa6BgAcZ2hyqPNC0Ra 2a10$FfLx/gxq.FyeOBb0nbaVeusLhQjASSdY7w45i1ACl/rcYQMmhaXV2 2a10$JdPXAxmuz.WTP5gxYiYseeKRSM/HTFzJJdACcDQ4MdhaaLmC0SjI. 2a10$yVEWf2MrwjCyi51rUKqQle/MZb7vwcOf6Gwp.hDT2ZUchlyAtJ4pO 2a10$FfJg2ATit7btKfJovL6zmug//8rzToQn7FO.fxOzo1KtNNfhWKuca 2a10$pOLMkd13n7i3DtVijLEqze1zeURpjtVz5rAx1qOAPqCQvjGG/d6D. 2a10$fQ32i8JsjjmqVRpiEsgT3ekTKtrfXn.JNl69beWEx0.YgdX.SEx5e 2a10$78brJFSdftip0XXYx4rS6ewdu4SiSsMIBY9oNcLhAZwg3GysRGk2m MIKE123 -> 2a10$U6KVh1NGxAIGYiM4YVgn6OAQt6ayAoLkh2lODv16rSpkS1iqfbR2C 2a10$t0FlEOBLEB8VwWJVoZRrweIRV0XyoBgm29c0SMqfqRK3ZBuvhgYbS 2a10$QpW6nHnWNhbTTjLq/NbzBu2Unp8ijwyPeUx2N2eMFWReFezosZ5fi 2a10$LtPzoQU0IluAgvP3/WhWquUv2AcDRh2ENhAeWDquiN/spitZYe/7q 2a10$Qcx7vUudzF7qzTjz.QpLKOby0tXQ4j.uqkInS1n4/6oD2r2eL0rZW 2a10$yZw7cdq1y9sjX8nZhYynseWjQ4jeVv76fPmBl.sg2xPvb8cyXD8Sq 2a10$kTmT6BQQE5LyRZ00Qas77.F5kxK0GxsW402ExosQswxmG.eBdgIZW 2a10$SRfHDNM.m3qX5y1O7V/cp.hQqgaXnKzfxBGRhLkAF39bufejuOieu 2a10$Sw5w2kTImJ5Y8UNlE/5/9OLaUgYxhCXU3P3gFBdEbs9PL8pCl60Q2 2a10$0mN8kNAl9GNr0c4K1Nr0b.MIcBW0QcPHB/f20hgeBuRfwvgZXT6hG
從以上輸出結果發現bcrypt算法與md5/sha算法有一個很大的區別,每次生成的hash值都是不同的,這樣暴力猜解起來或許要更困難一些。同時大家可能也發現了,加密后的字符長度比較長,有60位,所以用戶表中密碼字段的長度,如果打算采用bcrypt加密存儲,字段長度不得低於60.
二、spring-security.xml
<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd"> <http auto-config="true" use-expressions="true"> <intercept-url pattern="/admin**" access="hasRole('ADMIN')" /> <!-- access denied page --> <access-denied-handler error-page="/403" /> <form-login login-page="/login" default-target-url="/welcome" authentication-failure-url="/login?error" username-parameter="username" password-parameter="password" /> <logout logout-success-url="/login?logout" /> <!-- enable csrf protection --> <csrf /> </http> <!-- Select users and user_roles from database --> <authentication-manager> <authentication-provider> <password-encoder ref="encoder" /> <jdbc-user-service data-source-ref="dataSource" users-by-username-query="select d_username username,d_password password, d_enabled enabled from t_users where d_username=?" authorities-by-username-query="select d_username username, d_role role from t_user_roles where d_username=? " /> </authentication-provider> </authentication-manager> <beans:bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"> <beans:constructor-arg name="strength" value="9" /> </beans:bean> </beans:beans>
對比上一節的內容,只是增加23行、30-33行
最后要做的事情,就是把db中原來明文的密碼值,改成經過bcrypt加密后的字符串即可。
tips:如果你仍然喜歡用傳統的sha算法來處理密碼,只要把23行改成 <password-encoder hash="sha" /> 就可以了