Je suis en train de migrer de Spring Boot 1.4.9 vers Spring Boot 2.0 et aussi vers Spring Security 5 et j'essaie de m'authentifier via OAuth 2. Mais j'obtiens cette erreur :
java.lang.IllegalArgumentException : Il n'y a pas de PasswordEncoder mappé pour l'id "null".
D'après la documentation de Sécurité du printemps 5 j'ai appris que le format de stockage du mot de passe a été modifié.
Dans mon code actuel, j'ai créé mon bean d'encodage de mot de passe comme :
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
Cependant, il m'a donné l'erreur suivante :
Le mot de passe codé ne ressemble pas à BCrypt
J'ai donc mis à jour l'encodeur selon le Sécurité du printemps 5 document à :
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
Maintenant, si je peux voir le mot de passe dans la base de données, il est stocké en tant que
{bcrypt}$2a$10$LoV/3z36G86x6Gn101aekuz3q9d7yfBp3jFn7dzNN/AL5630FyUQ
Avec cette 1ère erreur disparue et maintenant quand j'essaie de faire l'authentification j'obtiens l'erreur suivante :
java.lang.IllegalArgumentException : Il n'y a pas de PasswordEncoder mappé pour l'id "null".
Pour résoudre ce problème, j'ai essayé toutes les questions ci-dessous de Stackoverflow :
Voici une question similaire à la mienne mais sans réponse :
REMARQUE : Je stocke déjà le mot de passe crypté dans la base de données, il n'est donc pas nécessaire de le coder à nouveau dans la base de données. UserDetailsService
.
Dans le Sécurité du printemps 5 Ils ont suggéré que vous pouvez gérer cette exception en utilisant la documentation :
DelegatingPasswordEncoder.setDefaultPasswordEncoderForMatches(PasswordEncoder)
Si c'est le remède, où dois-je le mettre ? J'ai essayé de le mettre dans PasswordEncoder
haricot comme ci-dessous mais ça ne marchait pas :
DelegatingPasswordEncoder def = new DelegatingPasswordEncoder(idForEncode, encoders);
def.setDefaultPasswordEncoderForMatches(passwordEncoder);
Classe MyWebSecurity
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers(HttpMethod.OPTIONS)
.antMatchers("/api/user/add");
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
Configuration de MyOauth2
@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
@Bean
public DefaultAccessTokenConverter accessTokenConverter() {
return new DefaultAccessTokenConverter();
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints
.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancer())
.accessTokenConverter(accessTokenConverter())
.authenticationManager(authenticationManager);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("test")
.scopes("read", "write")
.authorities(Roles.ADMIN.name(), Roles.USER.name())
.authorizedGrantTypes("password", "refresh_token")
.secret("secret")
.accessTokenValiditySeconds(1800);
}
}
Veuillez m'aider à résoudre ce problème. J'ai passé des heures à le résoudre mais je n'y suis pas parvenu.
0 votes
J'ai été un peu plus descriptif du problème. Lorsque je suis passé de Spring security 4 à 5, j'ai eu une première erreur, puis je l'ai résolue en changeant mon générateur de mot de passe, et j'ai commencé à avoir une deuxième erreur. Et les messages d'erreur sont différents. 1) Le mot de passe codé ne ressemble pas à BCrypt et 2) java.lang.IllegalArgumentException : Il n'y a pas de PasswordEncoder mapped pour l'id "null". Deuxième problème que je rencontre actuellement.
3 votes
Je pense que le problème se situe au niveau du client (et non des comptes utilisateurs individuels). Personnellement, je codais déjà les détails de l'utilisateur, mais pas le client. Maintenant, les utilisateurs d'OAuth2 sont censés encoder les données de l'utilisateur. client secret (ainsi que les mots de passe des utilisateurs). Plus précisément, il faut soit définir l'option
passwordEncoder
sur leClientDetailsServiceConfigurer
ou préfixe le secret avec {noop}. J'espère que cela aura un sens et aidera quelqu'un.0 votes
Ce problème a été résolu pour moi en exécutant
mvn clean package
. Il doit y avoir un problème avec la mise en cache.