2

I'm sure this has been asked before, but I can't find anything that answers this problem.

With Spring-security, I'm using a password encoder.

<beans:bean class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" id="passwordEncoder"/>


    <authentication-manager>
         <authentication-provider user-service-ref='CustomUserDetailsService'>
         <password-encoder ref="passwordEncoder"/>
         </authentication-provider>
    </authentication-manager>

Within my UserDAOImpl I have the following code when adding a user...

@Override
public void addUser(final User user) {
    user.setPassword(passwordEncoder.encodePassword(user.getPassword(), "salt"));
    sessionFactory.getCurrentSession().save(user);
}

My password gets encoded correctly, but always gets read as invalid, which sort of makes sense as I don't know how Spring would know my salt was "salt" - how do you tell spring security as well as Hibernate to use the same salt? Am I missing something about how spring security manages passwords?

David
  • 19,577
  • 28
  • 108
  • 128

1 Answers1

4

The recommended way is to use a standard password encoder, that will use a random salt, ans store this salt with the digested password. This way, you don't need to provide any salt. If you want to provide your own salt, then you need to inject a SaltSource into the DAO authenticator, as explained by the documentation (and of course use the same source when you encode the password to create a new user):

The StandardPasswordEncoder in the crypto package uses a random 8-byte salt, which is stored in the same field as the password.

Note

The legacy approach to handling salt was to inject a SaltSource into the DaoAuthenticationProvider, which would obtain a salt value for a particular user and pass it to the PasswordEncoder. Using a random salt and combining it with the password data field means you don't have to worry about the details of salt handling (such as where the the value is stored), as it is all done internally. So we'd strongly recommend you use this approach unless you already have a system in place which stores the salt separately.

In your case, the SaltSource would always return the "salt". Note that this way of salting is insecure, because all the users sharing a common password (yes, it happens) end up with the same hashed password. This means that an attacker finding the password of one user also finds the password of all the users sharing the same password.

Community
  • 1
  • 1
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • 1
    The recommended option these days is to use [BCrypt](http://stackoverflow.com/a/8528804/241990). Just inject a `BCryptPasswordEncoder` into your Hibernate DAO (or instantiate one internally), use it to create the hash and use the same bean for your authentication. The salt will be taken care of automatically. – Shaun the Sheep Jul 07 '12 at 17:09
  • @LukeTaylor: thanks for the information. TODO: recommend that in the documentation :-) – JB Nizet Jul 07 '12 at 17:21