with secure mkyong example autoconfigure and java spring spring-boot spring-security spring-security-oauth2

java - secure - Spring Security 5: No hay un PasswordEncoder asignado para el ID "null"



spring security oauth2 example mkyong (2)

Estoy migrando de Spring Boot 1.4.9 a Spring Boot 2.0 y también a Spring Security 5 y estoy tratando de autenticarme a través de OAuth 2. Pero recibo este error:

java.lang.IllegalArgumentException: No hay un PasswordEncoder asignado para el id "null

De la documentación de Spring Security 5 , llego a saber que el formato de almacenamiento para la contraseña ha cambiado.

En mi código actual, he creado mi codificador de contraseña como:

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

Sin embargo me estaba dando por debajo del error:

La contraseña codificada no se parece a BCrypt

Así que actualizo el codificador según el documento Spring Security 5 para:

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

Ahora si puedo ver la contraseña en la base de datos se está almacenando como

{bcrypt}$2a$10$LoV/3z36G86x6Gn101aekuz3q9d7yfBp3jFn7dzNN/AL5630FyUQ

Con ese primer error desaparecido y ahora cuando intento realizar la autenticación, obtengo un error inferior al siguiente:

java.lang.IllegalArgumentException: No hay un PasswordEncoder asignado para el id "null

Para resolver este problema, probé todas las siguientes preguntas de Stackoverflow:

Aquí hay una pregunta similar a la mía pero no contestada:

NOTA: Ya estoy almacenando la contraseña cifrada en la base de datos, por lo que no es necesario codificar nuevamente en UserDetailsService .

En la documentación de seguridad de Spring 5 sugirieron que puedes manejar esta excepción usando:

DelegatingPasswordEncoder.setDefaultPasswordEncoderForMatches (PasswordEncoder)

Si esta es la solución, ¿dónde debería ponerla? He intentado ponerlo en el bean PasswordEncoder como abajo, pero no funcionó:

DelegatingPasswordEncoder def = new DelegatingPasswordEncoder(idForEncode, encoders); def.setDefaultPasswordEncoderForMatches(passwordEncoder);

Clase 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(); } }

Configuración 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); } }

Por favor guíame con este tema. He pasado horas para arreglar esto pero no puedo arreglarlo.



Para cualquier persona que enfrente el mismo problema y no necesite una solución segura, principalmente para pruebas y depuración, los usuarios de la memoria aún pueden configurarse.

Esto es solo para jugar - no hay un escenario del mundo real.

El enfoque utilizado a continuación está en desuso.

Aquí es donde lo obtuve de:

Dentro de su WebSecurityConfigurerAdapter agregue lo siguiente:

@SuppressWarnings("deprecation") @Bean public static NoOpPasswordEncoder passwordEncoder() { return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance(); }

Aquí, obviamente, las contraseñas están hasheadas, pero aún están disponibles en la memoria.

Por supuesto, también podría usar un PasswordEncoder real como BCryptPasswordEncoder y prefijar la contraseña con el id correcto:

// Create an encoder with strength 16 BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16); String result = encoder.encode("myPassword"); assertTrue(encoder.matches("myPassword", result));