SpringSecurity------PasswordEncoder(二)
1、PasswordEncoder接口
Spring Security的PasswordEncoder接口用于密码的单向加密,保证密码的安全存储。Spring Security提供的PasswordEncoder都是单向加密,所以不能用于有双向转化需求的密码。PasswordEncoder用于加密存储密文,并在身份认证时将密文同用户提供的明文密码进行比较。
2、DelegatingPasswordEncoder委托类
在Spring Security 5.0之前,默认的PasswordEncoder是NoOpPasswordEncoder,使用的是纯文本密码(未加密),之后使用委托类DelegatingPasswordEncoder主要是考虑到以下几点:
- 兼容很多系统使用的旧密码加密器
- 最佳的密码加密方式可能再次改变
- 兼容低版本的Spring Security加密
Spring Security引进DelegatingPasswordEncoder解决所有以下问题:
-
可以保证密码加密使用当前推荐的加密策略
-
可以校验新格式和传统格式的密文
-
允许升级加密策略
你可以使用PasswordEncoderFactories快速构建一个DelegatingPasswordEncoder:
PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
或者,也可以通过下面的方式自定义构建实例:
String idForEncode = "bcrypt";
Map encoders = new HashMap<>();
encoders.put(idForEncode, new BCryptPasswordEncoder());
encoders.put("noop", NoOpPasswordEncoder.getInstance());
encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
encoders.put("scrypt", new SCryptPasswordEncoder());
encoders.put("sha256", new StandardPasswordEncoder());
PasswordEncoder passwordEncoder = new DelegatingPasswordEncoder(idForEncode, encoders);
3、密码存储格式
常规的密码存储格式如下:
{id}encodedPassword
id是指定使用那种PasswordEncoder的标识符,encodedPassword是原始的经过编码的密文。 这个id 必须放在密文的前面,而且使用{ }包裹。
例如,下面就是使用不同ID的密文密码,明文密码对应的都是“password”:
BCryptPasswordEncoder-->{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
NoOpPasswordEncoder-->{noop}password
Pbkdf2PasswordEncoder-->{pbkdf2}5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc
SCryptPasswordEncoder-->{scrypt}$e0801$8bWJaSu2IKSn9Z9kM+TPXfOc/9bdYSrN1oD9qfVThWEwdRTnO7re7Ei+fUZRJ68k9lTyuTeUp4of4g24hHnazw==$OAOec05+bXxvuu/1qZ6NUR+xQYvYv7BeL1QxwRpY5Pc=
StandardPasswordEncoder-->{sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0
4、密码匹配
通过密文前的ID属性去获取相应的PasswordEncoder,这种映射关系在DelegatingPasswordEncoder的构造器中有体现。
默认情况,如果提供的密文没有指定ID或是ID为null, matches(CharSequence, String) 会抛出IllegalArgumentException异常。但是可以通过DelegatingPasswordEncoder.setDefaultPasswordEncoderForMatches(PasswordEncoder)自定义处理方式。
5、密码存储配置
Spring Security默认使用DelegatingPasswordEncoder,但是可以通过显示注入一个 PasswordEncoder实现来更改这种默认配置。
@Bean
public static PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
6、密码修改
使用默认的密码修改地址 /change-password
http
.passwordManagement(Customizer.withDefaults())
使用自定义的密码修改地址 /update-password
http
.passwordManagement((management) -> management
.changePasswordPage("/update-password")
)
上一篇:SpringSecurity------引入方式和配置(一)
下一篇:SpringSecurity------CSRF跨站请求伪造(三)