You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

配置Spring Security OAuth2密码模式时遇无映射PasswordEncoder错误

解决Spring Security OAuth2中"There is no PasswordEncoder mapped for the id 'null'"错误

这个问题我之前帮不少开发者解决过,本质是Spring Security 5之后引入了密码编码标识机制,要求所有存储的密码必须带上对应的编码器ID前缀(比如{bcrypt}),或者在配置中明确指定默认的编码器,否则就会抛出这个"找不到对应ID的PasswordEncoder"的错误。结合你用的资源所有者密码凭证模式,咱们一步步来搞定:

错误原因拆解

Spring Security 5开始,密码存储格式必须是 {编码器ID}加密后的密码,比如BCrypt加密的密码要写成{bcrypt}$2a$10$xxxxxx...。如果你的用户密码没有加这个前缀,或者你的认证/OAuth2配置没有正确关联PasswordEncoder,校验密码时就会找不到对应的编码器,从而报错。

具体解决方案

1. 给存储的密码加上编码器前缀

不管你是用内存存储用户还是数据库存储,密码都要带上对应的前缀:

  • 内存认证的话,直接在密码前加{bcrypt}(比如"{bcrypt}" + passwordEncoder().encode("123456"))
  • 数据库存储的话,更新用户密码字段,加上{bcrypt}前缀,确保字段值是{bcrypt}+加密后的字符串

2. 完善WebSecurity配置类

你已经定义了BCryptPasswordEncoder的Bean,但还需要确保认证管理器正确使用它,同时暴露AuthenticationManager供OAuth2调用。完整的配置示例如下:

import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {

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

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 这里以内存认证为例,数据库认证同理,要指定passwordEncoder
        auth.inMemoryAuthentication()
                .withUser("testUser")
                // 注意密码要带{bcrypt}前缀,或者通过encoder.setDefaultPasswordEncoderForMatches指定默认编码器
                .password("{bcrypt}" + passwordEncoder().encode("testPass"))
                .roles("USER");
    }

    // 必须暴露这个Bean,OAuth2的授权服务器需要用到
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

3. 配置OAuth2授权服务器

还要确保你的授权服务器配置中,关联了PasswordEncoder和AuthenticationManager,示例代码:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        // 允许表单方式获取token,同时指定客户端密钥的编码器
        security.allowFormAuthenticationForClients()
                .passwordEncoder(passwordEncoder);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("testClient")
                // 客户端密钥也要带{bcrypt}前缀
                .secret("{bcrypt}" + passwordEncoder.encode("clientSecret"))
                .authorizedGrantTypes("password", "refresh_token")
                .scopes("read", "write");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // 关联认证管理器,处理密码模式的认证请求
        endpoints.authenticationManager(authenticationManager);
    }
}

4. Postman请求的正确姿势

发送/oauth/token的POST请求时,注意:

  • 请求头设置Content-Type: application/x-www-form-urlencoded
  • 请求参数要包含:grant_type=password、username=你的用户名、password=明文密码、client_id=客户端ID、client_secret=客户端密钥
  • 也可以用Basic Auth方式传递client_id和client_secret,Postman会自动生成Authorization头

验证

做完上面的配置后,重启应用,用Postman重新发送请求,应该就能正常获取access_token了。

内容的提问来源于stack exchange,提问作者Dung Nguyen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:55:24