Spring Security 5: Il n'y a pas de PasswordEncoder mappé pour l'id " null"
je suis en train de passer de la botte à ressort 1.4.9 à la botte à ressort 2.0 et aussi à la sécurité à ressort 5 et j'essaie de faire l'authentification via OAuth 2. Mais je reçois cette erreur:
de java.lang.IllegalArgumentException: il n'y a pas de PasswordEncoder cartographié pour l'id "null
de la documentation de Spring Security 5 , j'apprends que le format de stockage du mot de passe est modifié.
dans mon code actuel j'ai créé mon encodeur de mot de passe bean comme:
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
mais il me donnait d'erreur ci-dessous:
le mot de passe encodé ne ressemble pas à BCrypt
donc je mets à jour l'encodeur selon le Spring Security 5 document à:
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
maintenant si je peux voir mot de passe dans la base de données il est stockage en tant que
{bcrypt}a$LoV/3z36G86x6Gn101aekuz3q9d7yfBp3jFn7dzNN/AL5630FyUQ
Avec cette 1ère erreur disparu et maintenant quand j'essaie de faire de l'authentification, je suis d'erreur ci-dessous:
de java.lang.IllegalArgumentException: il n'y a pas de PasswordEncoder cartographié pour l'id "null
pour résoudre ce problème j'ai essayé toutes les questions ci-dessous de Stackoverflow:
-
Passwordencoder Pour Bottes De Printemps Erreur
-
Printemps Oauth2. L'encodeur de mot de passe n'est pas défini dans Dao-AuthenticationProvider
Voici une question semblable à la mienne mais sans réponse:
- Printemps De Sécurité 5 - Migration Des Mots De Passe
NOTE: je stocke déjà un mot de passe crypté dans la base de données donc non besoin d'encoder à nouveau dans UserDetailsService
.
dans la documentation Spring security 5 ils ont suggéré que vous pouvez gérer cette exception en utilisant:
DelegatingPasswordEncoder.setDefaultPasswordEncoderForMatches (PasswordEncoder)
si c'est la solution, Où dois-je la mettre? J'ai essayé de le mettre dans PasswordEncoder
bean comme ci-dessous mais il ne fonctionnait pas:
DelegatingPasswordEncoder def = new DelegatingPasswordEncoder(idForEncode, encoders);
def.setDefaultPasswordEncoderForMatches(passwordEncoder);
MyWebSecurity classe
@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();
}
}
Myoauth2 Configuration
@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);
}
}
guidez-moi avec ce numéro. J'ai passer des heures à résoudre ce problème, mais pas en mesure de corriger.
2 réponses
lorsque vous configurez le ClientDetailsServiceConfigurer
, vous devez également appliquer le nouveau format de stockage de mot de passe au secret client.
.secret("{noop}secret")
pour toute personne confrontée au même problème et n'ayant pas besoin d'une solution sécurisée - pour le test et le débogage principalement - en mémoire les utilisateurs peuvent encore être configurés.
Ceci est juste pour jouer autour - pas de scénario du monde réel.
l'approche utilisée ci-dessous est dépréciée.
C'est de là que je l'ai obtenu:
dans votre WebSecurityConfigurerAdapter
ajouter le suivant:
@SuppressWarnings("deprecation")
@Bean
public static NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
ici, évidemment, les mots de passe sont hachés, mais sont toujours disponibles en mémoire.
bien sûr, vous pouvez aussi utiliser un vrai PasswordEncoder
comme BCryptPasswordEncoder
et préfixer le mot de passe avec le bon id:
// Create an encoder with strength 16
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16);
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));