I'm trying to add a salt when adding a new user/pwd, but the docs seem to be missing how to do this.
Here's a basic example:
<authentication-manager> <authentication-provider user-service-ref="userDetailsService"> <password-encoder hash="md5"> <salt-source user-property="username"/> </password-encoder> </authentication-provider> </authentication-manager>
You can see by the example that neither a custom salt or custom password encoder is used.
So, how would I wire the Salt in when adding a new user/pwd? I'd assume it would be something along the lines of:
@Autowired SaltSource saltSource; protected void foo(final CustomUser user) { final PasswordEncoder encoder = new Md5PasswordEncoder(); user.setPassword(encoder.encodePassword(user.getPassword(), saltSource)); }
However, since I am using the default salt/password encoders and I don't have a custom salt bean the autowire would fail.
Any clue how to make this work?
A salt is a sequence of randomly generated bytes that is hashed along with the password. The salt is stored in the storage and doesn't need to be protected. Whenever the user tries to authenticate, the user's password is hashed with the saved salt and the result should match the stored password.
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.
To verify the user entered the correct password, use the same one way hash against their entered value and then compare it with the previously hashed value - if they are the same, then the entered password is correct.
Class BCryptPasswordEncoderImplementation of PasswordEncoder that uses the BCrypt strong hashing function. Clients can optionally supply a "strength" (a.k.a. log rounds in BCrypt) and a SecureRandom instance. The larger the strength parameter the more work will have to be done (exponentially) to hash the passwords.
You don't autowire the SaltSource
when adding user. The SaltSource
is an abstraction used by Spring to provide the source of the salt for password checking only.
To create a properly encoded password hash You just past the salt itself to the PasswordEncoder
- the value of username
property, not the SaltSource
:
private PasswordEncoder encoder = new Md5PasswordEncoder(); public User createUser(String username, String plainTextPassword) { User u = new User(); u.setUsername(username); u.setPassword(encoder.encodePassword(plainTextPassword, username)); getEntityManager().persist(u); // optional return u; }
Moreover the autowire of SaltSource
won't work until it's defined as an inner bean. You could define the ReflectionSaltSource
as top level bean and pass it's ID to the password-encoder
, i.e.:
<bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource" p:userPropertyToUse="username" /> <bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" /> <bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider" p:passwordEncoder-ref="passwordEncoder" p:saltSource-ref="saltSource" p:userDetailsService-ref="userDetailsService" /> <authentication-manager> <authentication-provider ref="daoAuthenticationProvider" /> </authentication-manager>
And then:
@Autowired private PasswordEncoder passwordEncoder; @Autowired private SaltSource saltSource; public CustomUserDetails createUser(String username, String plainTextPassword) { CustomUserDetails u = new CustomUserDetails(); u.setUsername(username); u.setPassword(passwordEncoder.encodePassword( plainTextPassword, saltSource.getSalt(u))); getEntityNamager().persist(u); // optional return u; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With