SpringSecurity中的密码加密
今天给大家介绍一下Spring Security中的密码加密的相关源码:
SpringSecurity中默认的加密方案是DelegatingPasswordEncoder 它是一个代理类,主要用来代理不同的密码加密方案,它是由PasswordEncoderFactories的createDelegatingPasswordEncoder方法提供默认的DelegatingPasswordEncoder实例,可以看到默认加密方案是bcrypt
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() {
}
DelegatingPasswordEncoder实现了PasswordEncoder接口,
实现encode接口,加密完成后给加密后的字符串添加前缀,表示采用的哪种加密方案。
public String encode(CharSequence rawPassword) {
return "{" + this.idForEncode + "}" + this.passwordEncoderForEncode.encode(rawPassword);
}
实现密码匹配接口:
public boolean matches(CharSequence rawPassword, String prefixEncodedPassword) {
if (rawPassword == null && prefixEncodedPassword == null) {
return true;
} else {
String id = this.extractId(prefixEncodedPassword);
PasswordEncoder delegate = (PasswordEncoder)this.idToPasswordEncoder.get(id);
if (delegate == null) {
return this.defaultPasswordEncoderForMatches.matches(rawPassword, prefixEncodedPassword);
} else {
String encodedPassword = this.extractEncodedPassword(prefixEncodedPassword);
return delegate.matches(rawPassword, encodedPassword);
}
}
}
private String extractId(String prefixEncodedPassword) {
if (prefixEncodedPassword == null) {
return null;
} else {
int start = prefixEncodedPassword.indexOf("{");
if (start != 0) {
return null;
} else {
int end = prefixEncodedPassword.indexOf("}", start);
return end < 0 ? null : prefixEncodedPassword.substring(start + 1, end);
}
}
}
先调用extractId方法从加密字符串中提取具体的加密方案,就是{ }中的字符,拿到后从idToPasswordEncoder中匹配,为null采用默认的defaultPasswordEncoderForMatches的密码匹配器进行匹配。
开发者向spring容器中注册一个PasswordEncoder实例,AuthenticationManager使用该实例,没有提供就使用DelegatingPasswordEncoder的实例。
好了 这就是Spring Security的密码加密相关的源码了。