Table of Contents

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<GrantedAuthority> 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<GrantedAuthority> getGrantedAuthorities()
    {
    	return grantedAuthorities;
    }
 
	public void setGrantedAuthorities(List<GrantedAuthority> grantedAuthorities)
    {
    	this.grantedAuthorities = grantedAuthorities;
    }
 
	public void setGrantedAuthoritiesByName(List<String> grantedAuthorities)
	{
		ArrayList<GrantedAuthority> definitiveList = new ArrayList<GrantedAuthority>();
 
		Iterator<String> 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<GrantedAuthority> 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

	<!-- 
 
	Create user administrator.............................................
 
	WARNING!!!! USE IT ONLY THE FIRST TIME TO SET UP THE FIRST USER!!!!!
 
	Uncomment this bean only to create programmatically the administrator
	(or other users) and only for fresh installations
 
	 -->
	<bean id="batchUserCreator"
		class="com.supermanhamuerto.util.BatchUserCreator"
		init-method="createUser"
		scope="singleton">
		<property name="userDetailsManager" ref="jdbcUserDetailsManager"/>
		<property name="saltSource" ref="saltSource"/>
		<property name="passwordEncoder" ref="passwordEncoder"/>
		<property name="username" value="MY-USERNAME-GOES-HERE"/>
		<property name="password" value="MY-SECRET-PASSWORD-GOES-HERE"/>
		<property name="enabled" value="true"/>
		<property name="accountNonExpired" value="true"/>
		<property name="accountNonLocked" value="true"/>
		<property name="grantedAuthoritiesByName">
			<list>
				<value>ROLE_GUEST</value>
				<value>ROLE_USER</value>
				<value>ROLE_BOARD</value>
				<value>ROLE_ADMIN</value>
				<value>ROLE_MEMBER</value>
			</list>
		</property>
	</bean>

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~~