这是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(我之前的问题的原因)。
感谢回复我之前的问题的评论,好像我需要用{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'
给出&#34;消息&#34;:&#34;没有为id \&#34; null \&#34;&#34;映射的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();
}
对于授权服务器,请确保您同时参考AuthorizationServerSecurityConifgurer
和ClientDetailsServiceConfigurer
部分。
@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端点。
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中看到的内容之外)。