spring security中的密碼加密:BCrypt算法工具類BCryptPasswordEncoder
??spring security中有多種密碼加密方式咨跌,MD5算法的Md5PasswordEncoder沾凄、SHA 算法的ShaPasswordEncoder沙廉,但由于是弱加密算法处面,都被棄用了饺谬。推薦使用的是BCrypt算法的BCryptPasswordEncoder。
一递胧、BCryptPasswordEncoder的使用
(一)添加依賴
??在SpringBoot項(xiàng)目中加入spring security依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
(二)放行請(qǐng)求
??添加了spring security依賴后,所有的請(qǐng)求都被spring security所控制了赡茸,這里只是使用BCrypt密碼加密的部分缎脾,所以需要編寫配置類,配置為所有地址都可以匿名訪問(wèn)占卧。
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
/**
* @author chushiyan
* @email Y2h1c2hpeWFuMDQxNUAxNjMuY29t(base64)
* @description
*/
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/**").permitAll()
.anyRequest().authenticated()
.and().csrf().disable();
}
}
(三)啟動(dòng)類中配置bean
@Bean
public BCryptPasswordEncoder getBcryptPasswordEncoder(){
return new BCryptPasswordEncoder();
}
(四)加密密碼
// 加密密碼
user.setPassword(bCryptPasswordEncoder.encode(password));
(五)校驗(yàn)密碼
// 參數(shù)一:待檢驗(yàn)的遗菠、未加密的密碼
// 參數(shù)二:從數(shù)據(jù)庫(kù)中查詢出的加密后密碼
bCryptPasswordEncoder.matches(password, userFromDB.getPassword())
二、深入了解BCryptPasswordEncoder
(一)測(cè)試生成密碼
/**
* @author chushiyan
* @email Y2h1c2hpeWFuMDQxNUAxNjMuY29t(base64)
* @description
*/
@SpringBootTest
class ApplicationTests {
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Test
public void testBCryptPasswordEncoder() {
for (int i = 0; i < 10; i++) {
String password = "123456";
String hashed = bCryptPasswordEncoder.encode(password);
System.out.println(hashed);
}
}
}
??控制臺(tái)輸出:
$2a$10$A/Jty.uPopRKNL/Pagnhvufb9sPScp74h93qHGxFztBlrzdOJU66a
$2a$10$I4q0m0Tesq5GRLETEyXOPObHaI8JYGohK1m/63KtAKjRjHws1.Fi.
$2a$10$ByPK1poz.JRGSlO/F9CiqexXW2VEgeaScjuQPLPqksLRGv8xtd5uy
$2a$10$vs3Vj7BiQGRnjIWq895CXunLUyDAVRrZccJR/ggMy/nWAiklUxXJC
$2a$10$4LKrbmr4u7q71yPq9PZLxOkCUCSo1Q.o73nfTXauIDCoKBMoFs7vG
$2a$10$Z5VD7fjGmze05VuWMJxVIuPXXO77YIFDVUi/XYQPnb6G3t8mikPJm
$2a$10$T39UcqdG73nfHLiqzYz.tOtTk7efiFUqmaqxew6xHL9gsBgFmpvCi
$2a$10$9VhF9phPI6VKSpy2ne3AteBfCZUBpWEkJoEh2uaGO.yONcl.fmP.2
$2a$10$gZv6eWEQ/TYwwHQJ1Hmex.v8XvcpzzyjIaoWjGOapYLanMMhrYBNW
$2a$10$ZVH0p2D0xRJ2CBIaWzdF5eT.4TKpSwDM7wP/IA4Qbv8u7lzOL7ipe
??為什么密碼都是123456华蜒,而加密后的結(jié)果不一樣辙纬?因?yàn)锽CryptPasswordEncoder中的encode()內(nèi)部調(diào)用BCrypt類隨機(jī)生成了鹽(salt),加了不同的鹽進(jìn)行hash自然不一樣叭喜。
(二)詳解加密后的密碼
$2a$10$A/Jty.uPopRKNL/Pagnhvufb9sPScp74h93qHGxFztBlrzdOJU66a
加密后的密碼長(zhǎng)度為60(所以設(shè)計(jì)數(shù)據(jù)庫(kù)時(shí)得保證該字段長(zhǎng)度不小于60)
說(shuō)明 | |
---|---|
$ | 分割符 |
$2a | BCrypt加密算法版本贺拣,在BCryptPasswordEncoder類內(nèi)部定義了一個(gè)枚舉類,枚舉了3個(gè)加密算法版本: public enum BCryptVersion { 2a"), 2y"), 2b"); 可以通過(guò)構(gòu)造函數(shù)指定版本:public BCryptPasswordEncoder(BCryptVersion version) 如:new BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion.$2A); |
$10 | 表示10次循環(huán)加鹽salt捂蕴。默認(rèn)10次纵柿,最少4次,最多31次启绰。 可以通過(guò)構(gòu)造函數(shù)指定次數(shù):public BCryptPasswordEncoder(int strength) |
10$之后的22位 | 鹽昂儒。BCryptPasswordEncoder內(nèi)部調(diào)用BCrypt的gensalt()方法隨機(jī)生成 |
最后的31位 | 明文密碼password和鹽hash后的值 |
三、非SpringBoot項(xiàng)目使用BCrypt加密算法
??BCrypt是一個(gè)算法委可,各個(gè)語(yǔ)言都有自己的實(shí)現(xiàn)渊跋。在java中有jBCrypt,spring security中也實(shí)現(xiàn)了BCrypt算法(沒(méi)有依賴jBCrypt)着倾。
??如果不是SpringBoot項(xiàng)目拾酝,就可以使用jBCrypt。
??官網(wǎng)示例:
// Hash a password for the first time
String hashed = BCrypt.hashpw(password, BCrypt.gensalt());
// gensalt's log_rounds parameter determines the complexity
// the work factor is 2**log_rounds, and the default is 10
String hashed = BCrypt.hashpw(password, BCrypt.gensalt(12));
// Check that an unencrypted password matches one that has
// previously been hashed
if (BCrypt.checkpw(candidate, hashed))
System.out.println("It matches");
else
System.out.println("It does not match");
導(dǎo)包:
<dependency>
<groupId>org.mindrot</groupId>
<artifactId>jbcrypt</artifactId>
<version>0.4</version>
</dependency>
或者加入jbcrypt-0.4.jar(這個(gè)包其實(shí)就BCrypt.java這一個(gè)類)