Is there a tutorial there, or anyone has pointers on how to do the following with Spring-Security?
A task:
I need to get salt from my database for authentication of the user name and use it to encrypt the password provided (from the login page) in order to compare it with the stored encrypted password (aka authenticate the user).
Additional Information:
I am using a custom database structure. The UserDetails object is created through the user-defined UserDetailsService , which in turn uses the custom DAOProvider to retrieve information from the database.
my security.xml :
<authentication-manager> <authentication-provider user-service-ref="userDetailsService"> </authentication-provider> </authentication-manager>
now i think i need
<password-encoder hash="sha" />
but what else? How to tell spring security to use the salt database to encode the password?
change
I found this SO post to be informative, but not sufficient: if I define the salt source in my xml that the password codec will use, like this:
<password-encoder ref="passwordEncoder"> <salt-source ref="saltSource"/> </password-encoder>
I need to write my own SaltSource to use my solid salt. But this should not be found inside the UserDetails object. So that...
Alternative 1:
Can I use a custom implementation of UserDetails that can have the salt property?
<beans:bean id="saltSource" class="path.to.MySaltSource" p:userPropertyToUse="salt"/>
and
@Service("userDetailsService") public class UserDetailsServiceImpl implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
user user class:
public class UserDetailsImpl extends User{
security.xml:
<authentication-manager> <authentication-provider user-service-ref="userDetailsService"> <password-encoder hash="sha"> <salt-source ref="saltSource"/> </password-encoder> </authentication-provider> </authentication-manager> <beans:bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource" p:userPropertyToUse="salt"/>
Alternative 2:
Otherwise, I would have to enter my DAO account in SaltSource to extract the salt for the given userName from the database.
BUT: How does spring Security call SaltSource ? Always with saltSource.getSalt(userDetails) ?
Then I just need to make sure my SaltSource uses userDetails.accountName on my accountDAO to retrieve the salt.
Edit2:
Just found out that my approach is ... legacy .. :( So, I think, I'm just using StandardPasswordEncoder (which I still need to figure out how to use exactly).
BTW: I applied the first option with a UserDetails user class extending the User class and simply adding the salt property, which is then passed to SaltSource as userPropertyToUse, as suggested in the SO post mentioned in Edit 1 ...
EDIT 3:
Just got the job of StandardPasswordEncoder, so I will leave a few pointers here:
Use StandardPasswordEncoder for authentication:
<beans:bean id="encoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder"> </beans:bean> <authentication-manager> <authentication-provider user-service-ref="userDetailsService"> <password-encoder ref="encoder" /> </authentication-provider> </authentication-manager>
Does this require the Spring-security-crypto module in version 3.1.0.RC? as far as I know. Could not find repository since 3.0. versions (although somewhere he had versions included in 3.0.6, etc.). The docs also talk about spring security 3.1, so I thought I'd just go with that.
When creating a user (for me this can only be done by the administrator), I just use
StandardPasswordEncoder encoder = new StandardPasswordEncoder(); String result = encoder.encode(password);
and i finished.
Spring security will randomly create a salt and add it to the password string before storing it in the database, so no salt column is needed .
However, you can also provide a global salt as a constructor argument ( new StandardPasswordEncoder("12345"); ), but I did not know how to configure my security configuration to get this value from a bean instead of supplying a static string with <constructor-arg name="secret" value "12345" /> . But I do not know how much this is necessary in any case.