====== Create a user programmatically in Spring Security ======
===== Intro =====
Probably Google wouldn't honour this page at the top of the search engines when the user search for this stuff, however, here it goes my own solution to programmatically create a user using Spring Security.
This solution is compatible with **any configuration** you should have in Spring Security. The only thing you should do is to inject the proper beans into this component. Let's say that you use a passwordEncoder bean which is ''org.springframework.security.authentication.encoding.ShaPasswordEncoder'': the only thing you must do is to inject the same bean into this object to getting things to work.
Are you using a salt source?? No problem. Me too. Just inject your salt source into the ''saltSource'' property and that's all.
Aren't you using a salt source?? No problem. Just leave blank the ''saltSource'' property and that's all you have to do.
===== The code =====
package com.supermanhamuerto.util;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.authentication.dao.SaltSource;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.provisioning.JdbcUserDetailsManager;
import org.springframework.security.core.GrantedAuthority;
public class BatchUserCreator
{
private static Log log = LogFactory.getLog(BatchUserCreator.class);
private JdbcUserDetailsManager userDetailsManager;
private SaltSource saltSource = null;
private PasswordEncoder passwordEncoder = null;
private UserDetails user;
private String username;
private String password;
private boolean enabled;
private boolean accountNonExpired;
private boolean credentialsNonExpired;
private boolean accountNonLocked;
private List grantedAuthorities;
public JdbcUserDetailsManager getUserDetailsManager()
{
return userDetailsManager;
}
public void setUserDetailsManager(JdbcUserDetailsManager userDetailsManager)
{
this.userDetailsManager = userDetailsManager;
}
public SaltSource getSaltSource()
{
return saltSource;
}
public void setSaltSource(SaltSource saltSource)
{
this.saltSource = saltSource;
}
public PasswordEncoder getPasswordEncoder()
{
return passwordEncoder;
}
public void setPasswordEncoder(PasswordEncoder passwordEncoder)
{
this.passwordEncoder = passwordEncoder;
}
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
public boolean isEnabled()
{
return enabled;
}
public void setEnabled(boolean enabled)
{
this.enabled = enabled;
}
public boolean isAccountNonExpired()
{
return accountNonExpired;
}
public void setAccountNonExpired(boolean accountNonExpired)
{
this.accountNonExpired = accountNonExpired;
}
public boolean isCredentialsNonExpired()
{
return credentialsNonExpired;
}
public void setCredentialsNonExpired(boolean credentialsNonExpired)
{
this.credentialsNonExpired = credentialsNonExpired;
}
public boolean isAccountNonLocked()
{
return accountNonLocked;
}
public void setAccountNonLocked(boolean accountNonLocked)
{
this.accountNonLocked = accountNonLocked;
}
public List getGrantedAuthorities()
{
return grantedAuthorities;
}
public void setGrantedAuthorities(List grantedAuthorities)
{
this.grantedAuthorities = grantedAuthorities;
}
public void setGrantedAuthoritiesByName(List grantedAuthorities)
{
ArrayList definitiveList = new ArrayList();
Iterator itAuthString = grantedAuthorities.iterator();
while( itAuthString.hasNext() )
{
String roleName = itAuthString.next();
definitiveList.add( new SimpleGrantedAuthority( roleName ) );
} // while
this.grantedAuthorities = definitiveList;
}
public void createUser()
{
if( log.isWarnEnabled() )
{
log.warn( "Creating user with name " + username );
log.warn( "Authorities: " );
Iterator itAuth = grantedAuthorities.iterator();
while( itAuth.hasNext() )
{
GrantedAuthority auth = itAuth.next();
log.warn( auth.getAuthority() );
} // while
} // log.isWarnEnabled()
Object salt = null;
user = new User( username,
password,
enabled,
accountNonExpired,
credentialsNonExpired,
accountNonLocked,
grantedAuthorities );
if( this.saltSource != null )
{
salt = this.saltSource.getSalt( user );
}
// calculate what hashedPassword would be in this configuration
String hashedPassword = passwordEncoder.encodePassword( user.getPassword(), salt );
// create a new user with the hashed password
UserDetails userHashedPassword = new User( username,
hashedPassword,
enabled,
accountNonExpired,
credentialsNonExpired,
accountNonLocked,
grantedAuthorities );
// if the user extists, delete it
if( userDetailsManager.userExists( userHashedPassword.getUsername() ) )
{
userDetailsManager.deleteUser( userHashedPassword.getUsername() );
}
// and finally, create the user
userDetailsManager.createUser( userHashedPassword );
}
}
===== An example of the applicationContext.xml =====
ROLE_GUEST
ROLE_USER
ROLE_BOARD
ROLE_ADMIN
ROLE_MEMBER
===== The resources =====
Of course, I've read the Spring Security source code to locate the exact point where the password is encoded and compared with the stored password. Is this point:
http://www.jarvana.com/jarvana/view/org/springframework/security/spring-security-core/3.0.2.RELEASE/spring-security-core-3.0.2.RELEASE-sources.jar!/org/springframework/security/authentication/encoding/MessageDigestPasswordEncoder.java?format=ok
Locate the function ''isPasswordValid''. Has this code:
public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
String pass1 = "" + encPass;
String pass2 = encodePassword(rawPass, salt);
return pass1.equals(pass2);
}
So, ''encodePassword'' is the function we need to call. But hold on!!! How is this ''Object salt'' yielded??? If you look here:
http://www.jarvana.com/jarvana/view/org/springframework/security/spring-security-core/3.0.2.RELEASE/spring-security-core-3.0.2.RELEASE-sources.jar!/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java?format=ok
you will see this code:
Object salt = null;
if (this.saltSource != null) {
salt = this.saltSource.getSalt(userDetails);
}
Which is exactly what we neeed.
~~DISQUS~~