密碼加密
Spring Security 內(nèi)置了加密機(jī)制
只需要實(shí)現(xiàn)PasswordEncoder接口即可
接入BCrypt加密
自定義自己的加密類繼承BCryptPasswordEncoder
package com.yang.springsecurity.provider;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import java.util.regex.Pattern;
@Component
public class MyPasswordEncoder extends BCryptPasswordEncoder {
private Pattern BCRYPT_PATTERN = Pattern
.compile("\\A\\$2(a|y|b)?\\$(\\d\\d)\\$[./0-9A-Za-z]{53}");
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
//判斷系統(tǒng)之前的用戶是否是采用bcrypt加密,不是的就采用明文匹配
if (!BCRYPT_PATTERN.matcher(encodedPassword).matches()){
return rawPassword.toString().matches(encodedPassword);
}
return super.matches(rawPassword, encodedPassword);
}
}
修改配置應(yīng)用自己的加密
@Autowired
private MyPasswordEncoder myPasswordEncoder;
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
//添加AuthenticationProvider
auth.userDetailsService(myUserDetailsService).passwordEncoder(myPasswordEncoder);
}
注意:
新系統(tǒng)引入密碼加密,只需指定明確加密方式即可。
但如果老系統(tǒng)使用明文或者其它加密方式,現(xiàn)在要引入bcrypt加密方式可采用以下幾種方式
-
兼容
重新matches()方法,判斷系統(tǒng)之前的用戶是否是采用bcrypt加密,不是的就采用明文匹配
-
增量更新
判斷系統(tǒng)之前的用戶是否是采用bcrypt加密,不是的就采用明文匹配,則嘗試使用用戶輸入的密碼重新生成BCrypt密文,并寫回?cái)?shù)據(jù)庫。
以舊的加密方案作為基礎(chǔ)接入BCrypt加密。
例如,舊的方案是MD5加密,即數(shù)據(jù)庫中的所有
密碼都是 MD5形式的密碼,那么直接把這些密碼當(dāng)作明文,先“跑庫”生成 BCrypt 密文,再使用
encode 和 matches 兩個(gè)方法在執(zhí)行 BCrypt 加密之前都先用MD5運(yùn)算一遍即可。
SpringSecurity5.x 加密方式采用{Id}password的格式配置,這樣做遷移的時(shí)候系統(tǒng)可以兼容多種加密方式。
我們可以看一下PasswordEncoderFactories自帶的加密方式
public class PasswordEncoderFactories {
public static PasswordEncoder createDelegatingPasswordEncoder() {
String encodingId = "bcrypt";
Map<String, PasswordEncoder> encoders = new HashMap();
encoders.put(encodingId, new BCryptPasswordEncoder());
encoders.put("ldap", new LdapShaPasswordEncoder());
encoders.put("MD4", new Md4PasswordEncoder());
encoders.put("MD5", new MessageDigestPasswordEncoder("MD5"));
encoders.put("noop", NoOpPasswordEncoder.getInstance());
encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
encoders.put("scrypt", new SCryptPasswordEncoder());
encoders.put("SHA-1", new MessageDigestPasswordEncoder("SHA-1"));
encoders.put("SHA-256", new MessageDigestPasswordEncoder("SHA-256"));
encoders.put("sha256", new StandardPasswordEncoder());
encoders.put("argon2", new Argon2PasswordEncoder());
return new DelegatingPasswordEncoder(encodingId, encoders);
}
private PasswordEncoderFactories() {
}
}