Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot: How to specify the PasswordEncoder?

Currently I got the main class:

package com.recweb.springboot;  import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;   @SpringBootApplication /*@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})*/ public class SpringbootApplication {      public static void main(String[] args) {         SpringApplication.run(SpringbootApplication.class, args);     } } 

a members class (id, firstname..), a MemberController class:

package com.recweb.springboot;  import java.util.Arrays; import java.util.List;  import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;  @RestController public class MemberController {     @GetMapping("/members")     public List<Member> getAllUsers() {         return Arrays.asList(new Member(1, "amit"));     } } 

and a WebSecurityConfig class:

package com.recweb.springboot;  import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.provisioning.InMemoryUserDetailsManager;  @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter {      @Bean     public UserDetailsService userDetailsService() {         InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();         manager.createUser(User.withUsername("user").password("user").roles("USER").build());         return manager;     } } 

When i run "http://localhost:8080/members" i get a login page, i enter "user" as user & "user" as password and then i get the hardcoded Member. It worked fine, but then i right clicked on my project-Run as-Maven install (because i added a dependency, i don't know if that was necessary, first time with Maven too). Since then, when i enter "user" & "user" on the login page i get this error:

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"     at org.springframework.security.crypto.password.DelegatingPasswordEncoder$UnmappedIdPasswordEncoder.matches(DelegatingPasswordEncoder.java:233) ~[spring-security-core-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.security.crypto.password.DelegatingPasswordEncoder.matches(DelegatingPasswordEncoder.java:196) ~[spring-security-core-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.security.authentication.dao.DaoAuthenticationProvider.additionalAuthenticationChecks(DaoAuthenticationProvider.java:86) ~[spring-security-core-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:166) ~[spring-security-core-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174) ~[spring-security-core-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199) ~[spring-security-core-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:124) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]     at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]     at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]     at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]     at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]     at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]     at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]     at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]     at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]     at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) ~[tomcat-embed-core-8.5.23.jar:8.5.23]     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.23.jar:8.5.23]     at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.23.jar:8.5.23]     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.23.jar:8.5.23]     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.23.jar:8.5.23]     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.23.jar:8.5.23]     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.23.jar:8.5.23]     at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.23.jar:8.5.23]     at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.23.jar:8.5.23]     at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.23.jar:8.5.23]     at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.23.jar:8.5.23]     at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.23.jar:8.5.23]     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131]     at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.23.jar:8.5.23]     at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131] 

and it stays on the login page. I tried to remove the dependency & Maven install again, but no luck. This is my POM:

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">     <modelVersion>4.0.0</modelVersion>      <groupId>com.recweb</groupId>     <artifactId>springboot</artifactId>     <version>0.0.1-SNAPSHOT</version>     <packaging>jar</packaging>      <name>springboot</name>     <description>Demo project for Spring Boot</description>      <parent>         <groupId>org.springframework.boot</groupId>         <artifactId>spring-boot-starter-parent</artifactId>         <version>2.0.0.BUILD-SNAPSHOT</version>         <relativePath/> <!-- lookup parent from repository -->     </parent>      <properties>         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>         <java.version>1.8</java.version>     </properties>      <dependencies>         <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-data-jpa</artifactId>         </dependency>         <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-data-rest</artifactId>         </dependency>         <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-jdbc</artifactId>         </dependency>         <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-security</artifactId>         </dependency>         <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-web</artifactId>         </dependency>          <dependency>             <groupId>com.h2database</groupId>             <artifactId>h2</artifactId>             <scope>runtime</scope>                 </dependency>         <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-test</artifactId>             <scope>test</scope>         </dependency>         <dependency>             <groupId>org.springframework.security</groupId>             <artifactId>spring-security-test</artifactId>             <scope>test</scope>         </dependency> <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator --> <dependency>     <groupId>org.hibernate</groupId>     <artifactId>hibernate-validator</artifactId>     <version>5.3.0.Final</version> </dependency>         <dependency>         <groupId>org.springframework.boot</groupId>         <artifactId>spring-boot-starter-tomcat</artifactId> <!--         <scope>provided</scope> --> </dependency>      </dependencies>      <build>         <plugins>             <plugin>                 <groupId>org.springframework.boot</groupId>                 <artifactId>spring-boot-maven-plugin</artifactId>             </plugin>         </plugins>     </build>      <repositories>         <repository>             <id>spring-snapshots</id>             <name>Spring Snapshots</name>             <url>https://repo.spring.io/snapshot</url>             <snapshots>                 <enabled>true</enabled>             </snapshots>         </repository>         <repository>             <id>spring-milestones</id>             <name>Spring Milestones</name>             <url>https://repo.spring.io/milestone</url>             <snapshots>                 <enabled>false</enabled>             </snapshots>         </repository>     </repositories>      <pluginRepositories>         <pluginRepository>             <id>spring-snapshots</id>             <name>Spring Snapshots</name>             <url>https://repo.spring.io/snapshot</url>             <snapshots>                 <enabled>true</enabled>             </snapshots>         </pluginRepository>         <pluginRepository>             <id>spring-milestones</id>             <name>Spring Milestones</name>             <url>https://repo.spring.io/milestone</url>             <snapshots>                 <enabled>false</enabled>             </snapshots>         </pluginRepository>     </pluginRepositories>   </project> 

What went wrong? Thanks

like image 578
Aa Yy Avatar asked Oct 29 '17 12:10

Aa Yy


People also ask

What is spring boot PasswordEncoder?

We use the PasswordEncoder that is defined in the Spring Security configuration to encode the password. In this example, the passwords are encoded with the bcrypt algorithm because we set the PasswordEncoder as the password encoder in the configuration. The code just saves the new user to the database.

How does Spring Security know password?

You use the same code that you already used to hash the password the first time, when the user created their userid/password. With a one way hash you don't decrypt the stored password, you hash the entered value and compare it with the already stored, hashed value.

How should spring passwords be stored?

Instead of using just the password as input to the hash function, random bytes (known as salt) would be generated for every users' password. The salt and the user's password would be ran through the hash function which produced a unique hash. The salt would be stored alongside the user's password in clear text.


2 Answers

In spring-security-core:5.0.0.RC1, the default PasswordEncoder is built as a DelegatingPasswordEncoder. When you store the users in memory, you are providing the passwords in plain text and when trying to retrieve the encoder from the DelegatingPasswordEncoder to validate the password it can't find one that matches the way in which these passwords were stored.

Use this way to create users instead.

User.withDefaultPasswordEncoder().username("user").password("user").roles("USER").build();  

You can also simply prefix {noop} to your passwords in order for the DelegatingPasswordEncoder use the NoOpPasswordEncoder to validate these passwords. Notice that NoOpPasswordEncoder is deprecated though, as it is not a good practice to store passwords in plain text.

User.withUsername("user").password("{noop}user").roles("USER").build(); 

For more information, check this post.

https://spring.io/blog/2017/11/01/spring-security-5-0-0-rc1-released#password-encoding

like image 102
dmendezg Avatar answered Oct 10 '22 11:10

dmendezg


Use NoOpPasswordEncoder for inMemoryAuthentication

auth.inMemoryAuthentication()     .withUser("user")     .password("{noop}password")     .roles("USER") 
like image 28
Nirbhay Rana Avatar answered Oct 10 '22 13:10

Nirbhay Rana