The following recipe shows how to create an encrypted password:
- To implement an encrypted authentication, let us start with a custom class, AppPasswordEncoder, that serves as a compendium of some popular PasswordEncoder APIs:
public class AppPasswordEncoder { public String md5Encoder(String password, String salt) { Md5PasswordEncoder md5PasswordEncoder = new Md5PasswordEncoder(); md5PasswordEncoder.setEncodeHashAsBase64(true); md5PasswordEncoder.setIterations(32); String encoded = md5PasswordEncoder.encodePassword(password,salt); return encoded; } public String bcryptEncoder(String password) { BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(); String encoded = bCryptPasswordEncoder.encode(password); return encoded; } public String standardEncoder(String password) { StandardPasswordEncoder standardPasswordEncoder = new StandardPasswordEncoder(); String encoded = standardPasswordEncoder.encode(password); return encoded; } }
Among these three built-in common PasswordEncoder, it is only Md5PasswordEncoder that has support for custom org.springframework.security.authentication.dao.SaltSource. The rest have a default internal salt generation. Save this file inside the org.packt.secured.mvc.core.password package.
- Slightly modify the getUserCredentials() method of UserServiceImpl to include the encoded password for each user. Md5PasswordEncoder is used for this recipe:
@Service("userService") public class UserServiceImpl implements UserService{ @Override public String getUserCredentials(String username) { Map<String, String> credentials = new HashMap<>(); AppPasswordEncoder encoder = new AppPasswordEncoder(); // Without salt /* credentials.put("sjctrags", encoder.md5Encoder("sjctrags", null)); credentials.put("admin", encoder.md5Encoder("admin", null)); credentials.put("hradmin", encoder.md5Encoder("hradmin", null)); */ // With Salt (username as salt) credentials.put("sjctrags", encoder.md5Encoder("sjctrags", "sjctrags")); credentials.put("admin", encoder.md5Encoder("admin", "admin")); credentials.put("hradmin", encoder.md5Encoder("hradmin", "hradmin")); return credentials.get(username); } @Override public Set<String> getuserRoles(String username) { // refer to sources } }
This recipe will be applying salt for every hashing procedure of Md5PasswordEncoder to strengthen the randomness of the hash generation. To disable salting, just set the second parameter of md5Encoder() to null.
- Now, create the security model AppSecurityModelE that will allow injection of the Md5PasswordEncoder bean into the container in order to encode the password of our UserDetails:
@Configuration @EnableWebSecurity public class AppSecurityModelE extends WebSecurityConfigurerAdapter{ // refer to sources @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // Hashing without salt // auth.userDetailsService(userDetailsService) // .passwordEncoder(md5PasswordEncoder()); // Hashing with salt auth.authenticationProvider(authProvider()); auth.eraseCredentials(false); } @Override protected void configure(HttpSecurity http) throws Exception { // refer to sources } @Override public void configure(WebSecurity web) throws Exception { // refer to sources } @Bean public Md5PasswordEncoder md5PasswordEncoder(){ Md5PasswordEncoder md5 = new Md5PasswordEncoder(); md5.setEncodeHashAsBase64(true); md5.setIterations(32); return md5; } @Bean public DaoAuthenticationProvider authProvider() { DaoAuthenticationProvider daoProvider = new DaoAuthenticationProvider(); daoProvider.setPasswordEncoder(md5PasswordEncoder()); daoProvider.setUserDetailsService(userDetailsService); ReflectionSaltSource saltHash = new ReflectionSaltSource(); saltHash.setUserPropertyToUse("username"); daoProvider.setSaltSource(saltHash); return daoProvider; } }
Since this recipe adds salt to hashing, the class org.springframework.security.authentication.dao.DaoAuthenticationProvider will be used to configure the encoding of userDetailsService using md5PasswordEncoder() with SaltSource.
- Update SpringContextConfig to consider the new security model.
- Save all files. build, install, and deploy the project.