Spring Security Password Encoding
January 06, 2020
This page will walk through Spring Security password encoding example. In Spring Security, the PasswordEncoder
interface is implemented to provide different type of password encoder such as Argon2PasswordEncoder
, BCryptPasswordEncoder
etc. In Spring Security 5.0, the default password encoder is DelegatingPasswordEncoder
.
To configure password encoder in
DaoAuthenticationProvider
, it provides setPasswordEncoder
method.
For LDAP authentication provider we can use
passwordEncoder
method of following inner class.
LdapAuthenticationProviderConfigurer.PasswordCompareConfigurer
<password-encoder>
element within <authentication-provider>
element.
Here on this page we will discuss to use different type of password encoder with examples.
Contents
Technologies Used
Find the technologies being used in our example.1. Java 11
2. Spring 5.2.1.RELEASE
3. Spring Boot 2.2.1.RELEASE
4. Maven 3.5.2
PasswordEncoder
Spring Security providesPasswordEncoder
interface that has different implementations for password encoding. The PasswordEncoder
has following methods.
1.
String encode(CharSequence rawPassword)
2.
boolean matches(CharSequence rawPassword, String encodedPassword)
3.
default boolean upgradeEncoding(String encodedPassword)
Find the implementations of
PasswordEncoder
interface.
1. Argon2PasswordEncoder, 2. BCryptPasswordEncoder
3. DelegatingPasswordEncoder, 4. LdapShaPasswordEncoder
5. Md4PasswordEncoder, 6. MessageDigestPasswordEncoder
7. NoOpPasswordEncoder, 8. Pbkdf2PasswordEncoder
9. SCryptPasswordEncoder, 10. StandardPasswordEncoder
Find the test class that shows encoding and matching password using different password encoders.
PasswordEncoderTest.java
package com.concretepage; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.security.crypto.argon2.Argon2PasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.factory.PasswordEncoderFactories; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder; import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; @ExtendWith(SpringExtension.class) @ContextConfiguration public class PasswordEncoderTest { @Test public void testBCrypt() { BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); String result = encoder.encode("ram123"); assertTrue(encoder.matches("ram123", result)); } @Test public void testArgon2() { Argon2PasswordEncoder encoder = new Argon2PasswordEncoder(); String result = encoder.encode("ram123"); assertTrue(encoder.matches("ram123", result)); } @Test public void testPbkdf2() { Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder(); String result = encoder.encode("ram123"); assertTrue(encoder.matches("ram123", result)); } @Test public void testSCrypt() { SCryptPasswordEncoder encoder = new SCryptPasswordEncoder(); String result = encoder.encode("ram123"); assertTrue(encoder.matches("ram123", result)); } @Test public void testDelegatingPasswordEncoder() { PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); String result = encoder.encode("ram123"); System.out.println(result); assertTrue(encoder.matches("ram123", result)); } }

BCryptPasswordEncoder
TheBCryptPasswordEncoder
is the implementation of PasswordEncoder
interface that uses the BCrypt strong hashing function. To instantiate BCryptPasswordEncoder
we can optionally pass BCrypt version and strength. Larger the strength value, more the work will be done to hash the password. We encode and match the password using BCryptPasswordEncoder
as following.
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); String result = encoder.encode("ram123"); assertTrue(encoder.matches("ram123", result));
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("lakhan") .password("$2a$10$q5pHs1fyVDbQSnBu3Il/meAONlMYFT1RhGlT2OC6IXX5.bp2JBZU6") .roles("USER"); } @Bean public PasswordEncoder passwordEncoder() { BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); return passwordEncoder; } ------ }
<password-encoder>
element.
<authentication-manager> <authentication-provider> <password-encoder ref="passwordEncoder"/> <user-service> <user name="lakhan" password="$2a$10$q5pHs1fyVDbQSnBu3Il/meAONlMYFT1RhGlT2OC6IXX5.bp2JBZU6" authorities="ROLE_USER" /> </user-service> </authentication-provider> </authentication-manager> <beans:bean name="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
Argon2PasswordEncoder
TheArgon2PasswordEncoder
is the implementation of PasswordEncoder
interface that uses the Argon2 hashing function. To instantiate Argon2PasswordEncoder
we can optionally pass the length of the salt, length of the generated hash, CPU cost parameter, memory cost parameter and parallelization parameter. To use Argon2PasswordEncoder
, we need to resolve Bouncy castle dependency.
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.64</version> </dependency>
Argon2PasswordEncoder
as following.
Argon2PasswordEncoder encoder = new Argon2PasswordEncoder(); String result = encoder.encode("ram123"); assertTrue(encoder.matches("ram123", result));
Argon2PasswordEncoder
, just create its bean.
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("ram") .password("$argon2id$v=19$m=4096,t=3,p=1$JudTbnHxqeGVs608XXVcTA$WB7CJvel59tcXBbsXhyq60et7wutd1DYSFufFX9uhtM") .roles("USER"); } @Bean public PasswordEncoder passwordEncoder() { Argon2PasswordEncoder passwordEncoder = new Argon2PasswordEncoder(); return passwordEncoder; } ------ }
<password-encoder>
element.
<beans:bean name="passwordEncoder" class="org.springframework.security.crypto.argon2.Argon2PasswordEncoder"/>
Pbkdf2PasswordEncoder
ThePbkdf2PasswordEncoder
is the implementation of PasswordEncoder
interface that uses PBKDF2 hashing function. To instantiate Pbkdf2PasswordEncoder
, we can optionally pass secret value to be included in the password hash, number of iteration and hash size. Find the example to encode and match password using Pbkdf2PasswordEncoder
.
Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder(); String result = encoder.encode("ram123"); assertTrue(encoder.matches("ram123", result));
Pbkdf2PasswordEncoder
in Spring Security Java configuration, just create its bean.
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("bharat") .password("77a366e9ba2d6830b64d1b86eb7462996f3102d2b76562de3e56e5f13543a02486e1ee553cef18de") .roles("USER"); } @Bean public PasswordEncoder passwordEncoder() { Pbkdf2PasswordEncoder passwordEncoder = new Pbkdf2PasswordEncoder(); return passwordEncoder; } ------ }
<password-encoder>
element.
<beans:bean name="passwordEncoder" class="org.springframework.security.crypto.password.Pbkdf2PasswordEncoder"/>
SCryptPasswordEncoder
TheSCryptPasswordEncoder
is the implementation of PasswordEncoder
interface that uses SCrypt hashing function. To instantiate SCryptPasswordEncoder
, we can optionally pass CPU cost, memory cost, parallelization parameter, key length for algorithm and salt length. To use SCryptPasswordEncoder
, we need to resolve Bouncy castle dependency. Find the example to encode and match password using SCryptPasswordEncoder
.
SCryptPasswordEncoder encoder = new SCryptPasswordEncoder(); String result = encoder.encode("ram123"); assertTrue(encoder.matches("ram123", result));
SCryptPasswordEncoder
in Spring Security Java configuration, just create its bean.
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("shatru") .password("$e0801$VoXA+5ot9fXbuLaOj5izqgd3JrOtBjvsqpbwssgHIA3omPpNB8t+FYtnsVpxx5DJjAvFtrA/klDstepB320TSw==$CLsjnAxzzNof2jkDrSBeoCTvuxO8qi67FRDY0vrCZwY=") .roles("USER"); } @Bean public PasswordEncoder passwordEncoder() { SCryptPasswordEncoder passwordEncoder = new SCryptPasswordEncoder(); return passwordEncoder; } ------ }
<password-encoder>
element.
<beans:bean name="passwordEncoder" class="org.springframework.security.crypto.scrypt.SCryptPasswordEncoder"/>
DelegatingPasswordEncoder
TheDelegatingPasswordEncoder
is the default password encoder in Spring Security 5.0. The DelegatingPasswordEncoder
delegates to another PasswordEncoder
based upon the prefixed identifier. For example,
1.
{noop}ram123
DelegatingPasswordEncoder
will delegate this password to NoOpPasswordEncoder
.
2.
{bcrypt}$2a$10$q5pHs1fyVDbQSnBu3Il/meAONlMYFT1RhGlT2OC6IXX5.bp2JBZU6
DelegatingPasswordEncoder
will delegate this password to BCryptPasswordEncoder
.
3.
{pbkdf2}77a366e9ba2d6830b64d1b86eb7462996f3102d2b76562de3e56e5f13543a02486e1ee553cef18de
DelegatingPasswordEncoder
will delegate this password to Pbkdf2PasswordEncoder
.
Find a complete example.
SecurityConfig.java
package com.concretepage; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/**").access("hasRole('USER')") .and().formLogin(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("ram") .password("{noop}ram123") //ram123 .roles("USER") .and() .withUser("lakhan") .password("{bcrypt}$2a$10$q5pHs1fyVDbQSnBu3Il/meAONlMYFT1RhGlT2OC6IXX5.bp2JBZU6") //lakhan123 .roles("USER"); } }
security-config.xml
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd"> <http> <intercept-url pattern="/**" access="hasRole('USER')" /> <form-login /> </http> <authentication-manager> <authentication-provider> <user-service> <user name="ram" password="{noop}ram123" authorities="ROLE_USER" /> <user name="lakhan" password="{bcrypt}$2a$10$q5pHs1fyVDbQSnBu3Il/meAONlMYFT1RhGlT2OC6IXX5.bp2JBZU6" authorities="ROLE_USER" /> </user-service> </authentication-provider> </authentication-manager> </beans:beans>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.1.RELEASE</version> <relativePath /> </parent> <properties> <context.path>spring-app</context.path> <java.version>11</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</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-test</artifactId> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.3.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.3.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-params</artifactId> <version>5.3.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-launcher</artifactId> <version>1.3.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.64</version> </dependency> </dependencies>
package com.concretepage; import org.springframework.security.core.Authentication; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class AppController { @GetMapping("/app") public @ResponseBody String helloUser(Authentication authentication) { return "Welcome! " + authentication.getName(); } }
package com.concretepage; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Main { public static void main(String[] args) { SpringApplication.run(Main.class, args); } }
Output
Download the project and run the following command from root folder of the project using command prompt.mvn spring-boot:run
http://localhost:8080/app

