There is no PasswordEncoder mapped for the id null 报错解决办法

springsecurity从4.2升级到5.0之后,做简单的登录,出现如下所示的错误:

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
	at org.springframework.security.crypto.password.DelegatingPasswordEncoder$UnmappedIdPasswordEncoder
.matches(DelegatingPasswordEncoder.java:238)
	at org.springframework.security.crypto.password.DelegatingPasswordEncoder.matches(DelegatingPasswordEncoder.java:198)

根据官方文档的资料和网上解决办法,需要做一些修改。

默认情况下与4.2版本不同的是,springsecurity5.0密码加密方式采用了bcrypt的方式,而且密码直接配置在xml文件中,不光是需要使用BCryptPasswordEncoder来加密,还需要指定一个encodingId,如果不指定,就会报出如题所示的错误。

我们可以看看PasswordEncoderFactories.createDelegatingPasswordEncoder()方法:

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());

		return new DelegatingPasswordEncoder(encodingId, encoders);
	}

这就是为什么说默认情况下使用的bcrypt方式加密。

知道了用什么方式,我们就可以来改进了。

1、密码不加密,和springsecurity4.2一样,使用明文密码,那就需要配置密码验证方式为noop,配置如下。

<beans:bean id="passwordEncoder" class="org.springframework.security.crypto.password.NoOpPasswordEncoder"></beans:bean>

在spring-security.xml配置文件中配置以上bean即可。

密码配置如下:

 <user name="admin" password="123456" authorities="ROLE_USER"/>
这样,默认密码就不需要进行加密,原样传入,原样匹配。这种配置方式密码前面,不需要加上{noop}

2、使用默认的密码加密方式,需要改动密码,并且密码格式如下:

{bcrypt}$2a$10$rY/0dflGbwW6L1yt4RVA4OH8aocD7tvMHoChyKY/XtS4DXKr.JbTC

在通过bcrypt方式加密之后的密文,前面加上{bcrypt}。

这里另外介绍两种方式来通过bcrypt方式加密,直接上源码:

package com.xxx.security.test;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;

public class PasswordEncoder {

    public static void main(String[] args) {
	org.springframework.security.crypto.password.PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
	String password = "123456";
	String password2 = encoder.encode(password);
	System.out.println(password2);
        System.out.println(encoder.matches(password, password2));
        
        BCryptPasswordEncoder encoder2 = new BCryptPasswordEncoder();
        String password3 = encoder2.encode(password);
        System.out.println(password3);
        System.out.println(encoder2.matches(password, password3));
    }

}

运行以上代码,打印结果如下:


眼尖的你,可能一下子就发现了一个小问题,通过bcrypt方式加密的密文,除了{bcrypt}外两次结果不一样,怎么会这样?

和以往加密方式不同的是,springsecurity5.0以上版本对bcrypt加密方式进行了随机数处理,所以每次产生的结果都不一样。不管是哪种方式,我们如果使用默认的加密方式,就需要在xml中配置密码为如下的样子。记得前面有{bcrypt}

{bcrypt}$2a$10$rY/0dflGbwW6L1yt4RVA4OH8aocD7tvMHoChyKY/XtS4DXKr.JbTC

报错的意思是说我们没有指定一个encodingId,最终在encoders map中没有匹配到encodingId。

如果我们需要使用MD5方式加密,我们就需要指定如下所示的密码:

{MD5}{pwegM3ORx1OzOc4eFzVztSPdeZit0BZPWTA5JB1Juc0=}dda279a014895996e55957976ec4cd36

同理,如果我们需要像springsecurity4.2那样,密码明文,我们可以这样配置:

<user name="admin" password="{noop}123456" authorities="ROLE_USER"/>

也无需像第一种方式那样在配置文件中增加NoOpPasswordEncoder的配置了。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luffy5459

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值