Spring Security中的Password Encoding

本文探讨了Spring Security中关于密码编码的重要概念,包括NoOpPasswordEncoder的弃用原因,推荐的BCryptPasswordEncoder、Pbkdf2PasswordEncoder和SCryptPasswordEncoder,以及如何使用DelegatingPasswordEncoder实现密码算法升级。通过DelegatingPasswordEncoder,可以支持多种密码加密算法并进行匹配,确保项目中的安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【目录】

  1. 背景
  2. 关于NoOpPasswordEncoding
  3. 其它Pasword Encoder
  4. 关于DelegatingPasswordEncoding
  5. 收获

0. 背景

在自定义配置Spring Security时,你或许会注意到这段代码。

	@Bean
	public static PasswordEncoder passwordEncoder() {
		return NoOpPasswordEncoder().getInstance();
	}

代码中提到的NoOpPasswordEncoder是什么?

关于NoOpPasswordEncoder

字面理解它是一个某某密码编译器(No Operate Password Encoder,即:无任何操作的密码密码编译器)。

看一下NoOpPasswordEncoder类的代码,通过注释了解到,该类已经弃用且不安全。它并不会对密码做什么操作,只是为了测试为目的的。也就是说在encode、matches过程中密码都是明文的。

所以在Spring文档中见到它,不足为奇了,因为它容易理解,但是真的在项目中使用Spring Security时不应该是NoOpPasswordEncoder.

其它Password Encoder

NoOpPasswordEncoder的注释中推荐我们有针对性的选择使用BCryptPasswordEncoder、Pbkdf2PasswordEncoder、SCryptPasswordEncoder中的一种。并推荐最好使用DelegatingPasswordEncoder,因为它支持密码升级。

暂时可以先这样理解:前三种都是根据某个算法对PasswordEncoder接口的具体实现,DelegatingPasswordEncoder是N种具体算法的代理实现。

通过这几个类的注释了解到BCryptPasswordEncoder、Pbkdf2PasswordEncoder、SCryptPasswordEncoder都是基于某种算法的PasswordEncoder接口的实现类。使用时需要根据需要,有选择的使用其中的一种即可。

比如我们想使用BCrypt算法来对密码加密,我们需要指定使用的PasswordEncoder是BCryptPasswordEncoder:

	@Bean
	public static PasswordEncoder passwordEncoder () {
		return new BCryptPasswordEncoder();
	}

在设定密码的,我们需要手动对明文的密码进行encode:

	String password = "123456";
	
	String encodedPassword = new BCryptPasswordEncoder().encode(password)

然后将encodedPassword密码进行保存。

如果我的项目开始选择A算法,后面改为B算法怎么办?如果A算法encode之后生成的密码是不可逆的,那么就自己编写这样一个逻辑:验证时先用A算法encode并match,成功后在用B算法encode并保存。好的事情Spring Security提供了现成的功能,那就是DelegatingPasswordEncoder。

关于DelegatingPasswordEncoder

DelegatingPasswordEncoder是N种算法实现的代理,通过DelegatingPasswordEncoder的实例,我们能够使用指定的算法进行encode,同时支持对旧的密码进行match。

你可以通过DelegatingPasswordEncoder的构造函数来实例化它:

String idForEncode = "bcrypt"; // 默认使用的encode算法的id

Map<String, PasswordEncoder> encoders = new HashMap<>();
encoders.put(idForEncoder, new BCryptPasswordEncoder());
encoders.put("noop", NoOpPasswordEncoder.getInstance());
encoders.put("pykdf2", new Pbkdf2PasswordEncoder());
encoders.put("scrypt", new SCryptPasswordEncoder());
encoders.put("sha256", new StandardPasswordEncoder());

PasswordEncoder passwordEncoder = new DelegatingPasswordEncoder(idForEncoder, encoders);

也可以使用PasswordEncoderFactories来获取DelegatingPasswordEncoder的一个实例。

PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();

要使用DelegatingPasswordEncoder,还需要了解一下3件事情:

  • 生成的密码结构
  • 如何利用密码结构来进行密码匹配
  • 如何指定当前要用的加密算法

下面逐一说明:

1,生成的密码结构如下:

{算法ID}加密后的内容

例如:

{bcrypt}$2a$10$lkbmWQlpkNpuVoYas5ZKl.zP.4F21IWeQAL4SSL.aEIb036o6vp3G	

{}中的bcrypt就是算法的ID

{}后面的字符串就是加密后的字符串

2,如何利用密码结构来进行密码匹配?

如果你使用A算法加密,生成的密码是

{A}adfadfadsfsdf

那么DelegatingPasswordEncoder就会根据算法ID({}中的值)来获取当前密码中使用的算法A,并用算法A对密码进行加密后在匹配。

如果原本使用A算法,后来改进使用了B算法,那么在DelegatingPasswordEncoder实例中添加B算法后。对旧密码(使用A算法生成的密码),通过算法ID,知道旧密码使用了A算法,并用A算法去加密匹配。对于新的密码,则直接使用B算法来进行加密、匹配。这样就支持了算法的升级。

3,如何指定当前使用哪种算法?

在DelegatingPasswordEncoder的有餐构造函数中,我们可以传递两个值来构造DelegatingPasswordEncoder的实例,如下:

new DelegatingPasswordEncoder(idForEncoder, encoders);

idForEncoder:DelegatingPasswordEncoder默认使用的算法ID

encoders:DelegatingPasswordEncoder中包含哪些PasswordEncoder

收获

通过浏览Spring Security中的PasswordEncoder代码,最终了解了PasswordEncoder这种密码升级的解决方案的一种良好的代码实现。

【Final】

建议阅读下面的参考,获取想要了解的更多细节。

【参考】

  1. 《Spring Security Reference》
  2. 《Spring Security 5.0的DelegatingPasswordEncoder详解》
  3. 《什么是框架》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值