There is no PasswordEncoder mapped for the id "null" 解决途径

WebSecurityConfig基于Spring Security OAuth2和 JWT 构建保护微服务系统 的搭建过程可参考 https://www.jianshu.com/p/24764aba1012?utm_source=oschina-app

 

如果按照上面链接搭建遇到如题的问题

有如下两种解决途径

1、在类 WebSecurityConfig 中添加如下代码

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

 

修改类OAuth2Config中的代码

    // 配置客户端基本信息
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory().withClient("user-service")// 创建一个客户端 名字是user-service
                .secret("$2a$10$AfWzWK7lF.TOFcZuifNjjeuA.OkFRlC6jYR.w33MtuH1d9.lKOMTy")
                .scopes("service")
                .authorizedGrantTypes("refresh_token", "password")
                .accessTokenValiditySeconds(3600);
    }

$2a$10$AfWzWK7lF.TOFcZuifNjjeuA.OkFRlC6jYR.w33MtuH1d9.lKOMTy 是123456的Base64编码

 

2 、修改类OAuth2Config中的代码,不修改WebSecurityConfig的代码

    // 配置客户端基本信息
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory().withClient("user-service")// 创建一个客户端 名字是user-service
                .secret("{bcrypt}$2a$10$AfWzWK7lF.TOFcZuifNjjeuA.OkFRlC6jYR.w33MtuH1d9.lKOMTy")
                .scopes("service")
                .authorizedGrantTypes("refresh_token", "password")
                .accessTokenValiditySeconds(3600);
    }

 

{bcrypt}$2a$10$AfWzWK7lF.TOFcZuifNjjeuA.OkFRlC6jYR.w33MtuH1d9.lKOMTy-----bcrypt 是因为是用该方式进行编码(还有其他很多种方式)

源码分析:

1、因为类中注入了passwordEncoder这个Bean

在 类WebSecurityConfig的父类 WebSecurityConfigurerAdapter方法中

        public boolean matches(CharSequence rawPassword, String encodedPassword) {
            return this.getPasswordEncoder().matches(rawPassword, encodedPassword);
        }

 

会进入 BCryptPasswordEncoder的matches方法来判断之前的Base64编码是否正确 

    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        if (encodedPassword != null && encodedPassword.length() != 0) {
            if (!this.BCRYPT_PATTERN.matcher(encodedPassword).matches()) {
                this.logger.warn("Encoded password does not look like BCrypt");
                return false;
            } else {
                return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
            }
        } else {
            this.logger.warn("Empty encoded password");
            return false;
        }
    }

 

2、因为没有初始化BCryptPasswordEncoder类,所以会进入DelegatingPasswordEncoder的matches方法 

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

 this.extractId()方法会以’{‘,’}‘截取字符串来判断要用什么encoder

所以要在Base64编码前加入 {bcrypt}

 

如果哪里有解释错误的,请不要喷,我只是一个卑微的码农

 

posted @ 2020-04-15 16:17  我爱瑞秋  阅读(1623)  评论(0)    收藏  举报