这是earlier question的后续行动 .

我正在尝试将OAuth2应用程序迁移到Spring Boot 2 / Security 5.根据我之前的问题(和this)中的一条评论,似乎密码的存储格式正在发生变化 .

在我原来的(Spring 1.5.9)应用程序中,我明确指定了BCrypt

// AppConfig

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

// SecurityConfig

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {


auth.userDetailsService(userService)    
.passwordEncoder(passwordEncoder);
}

这导致错误,密码“看起来不像BCrypt(我之前的问题的原因) .

感谢回复我之前的问题的评论,好像我需要用作为存储密码的前缀 . 我还用以下代码替换了我的PassowrdEncoder @Bean

PasswordEncoder passwordEncoder =
    PasswordEncoderFactories.createDelegatingPasswordEncoder();

但是,这导致以下错误:

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

接下来,我尝试将 @Bean 更改为以下内容:

@Bean
public PasswordEncoder passwordEncoder() {

    String idForEncode = "bcrypt";
    Map encoders = new HashMap<>();
    encoders.put(idForEncode, new BCryptPasswordEncoder());

    encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
    encoders.put("scrypt", new SCryptPasswordEncoder());

    return new DelegatingPasswordEncoder(idForEncode, encoders);

}

这导致了同样的错误 . 用户创建部分似乎按预期工作 . 运行以下内容:

@Bean
    public CommandLineRunner demo(UserRepository repository) {
        return(args) -> {
            OAuthUser user = new OAuthUser();


            user.setFirstName("K");
            user.setLastName("M");
            user.setPassword(passwordEncoder.encode("L"));
            user.setUserName("KLM");

repository.save(user);
        };
    }

导致密码为 {bcrypt}$2a$10$p/W7UV.fkghBRMzuDhh7z.G0uPLze9yFMLarbHdmwinzlqAHrMUQi 的用户 .

但是,用户验证失败 . 发出此请求:

curl --request POST \
  --url http://web:secret@localhost:8090/oauth/token \
  --header 'content-type: multipart/form-data; boundary=---011000010111000001101001' \
  --form grant_type=password \
  --form username=KLM \
  --form 'pasword =L'

给出“消息”:“没有为id \”null \“”消息映射PasswordEncoder .

首先,任何有关该问题的建议都将受到赞赏 .

其次,关于迁移到新的存储格式,我还有另一个问题 . 这种存储格式,即 {id]password ,是一种标准或特定于Spring的东西吗?基本上,在过去,如果密码存储为BCrypt,我可能会从C#或其他应用程序验证密码 . 需要知道的所有应用程序都是如何处理BCrypt标准 . 这种新的存储格式是否会抑制通过非Spring应用程序验证用户的能力?

谢谢 .

编辑:

我最终让Spring Boot 2 / Security 5与OAuth2一起工作 . 虽然我不记得确切的步骤(我一直在研究一些Spring项目),但我发布的是希望我的相关配置作为指导 .

确保添加密码编码器bean:

@Bean
    public PasswordEncoder passwordEncoder() {
return  PasswordEncoderFactories.createDelegatingPasswordEncoder();
        //return new BCryptPasswordEncoder();
    }

对于授权服务器,请确保在 AuthorizationServerSecurityConifgurerClientDetailsServiceConfigurer 部分中同时引用它们 .

@EnableAuthorizationServer
@Configuration
public class AuthConfig extends AuthorizationServerConfigurerAdapter {

// Some code omitted for brevity

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.passwordEncoder(passwordEncoder);
        security.checkTokenAccess("permitAll()");
        security.tokenKeyAccess("permitAll()");
    }


    @Override
    public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
        JdbcClientDetailsService details = new JdbcClientDetailsService(appConfig.dataSource());
        details.setPasswordEncoder(passwordEncoder);

        configurer.withClientDetails(details);
    }


    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
        endpoints.tokenStore(tokenStore).accessTokenConverter(converter)
        .userDetailsService(userService)
        .authenticationManager(authenticationManager);
    }

在SecurityConfig中,确保使用AuthenticationManagerBuilder注册它 .

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder);
    }

确保配置 ResourceServer ,包括HttpSecurity endpoints .

EnableResourceServer
@Configuration
public class ResourceConfig extends ResourceServerConfigurerAdapter {

    private AppConfig appConfig;

    @Autowired
    private ResourceServerTokenServices tokenService;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    public ResourceConfig(AuthenticationManager authenticationManager, AppConfig appConfig) {
        this.authenticationManager = authenticationManager;
        this.appConfig = appConfig;
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId("321");
        resources.tokenServices(tokenService);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.headers().frameOptions().disable().and().requestMatchers().and().authorizeRequests()
                .antMatchers("/user/**").hasAuthority("ROLE_ADMIN").antMatchers("/h2/**").permitAll();

    }

我相信这是最相关的 @Config 类 . 我的UserDetailsService实现没有什么特别之处,我认为我甚至没有在这个应用程序中扩展或自定义客户端(在@Config中看到的内容之外) .