Personally, for the administrator account, I will not use the basic Spring Security user service, mainly because it lacks the flexibility of a database-based user management approach. Indeed, you probably do not want your administrator credentials to be set once for everyone, as they can be guessed or stolen or just forgotten.
Conversely, for all accounts, including administrative, both password modification and password recovery mechanisms should be created , including administrative (provided that you use a reliable email account to recover the password, but this is a reasonable assumption).
Having a specific approach, my approach is this: I use AuthenticationManager , where I insert CustomUserDetailService
<authentication-manager alias="authenticationManager"> <authentication-provider user-service-ref="customUserDetailsService" > <password-encoder ref="passwordEncoder" /> </authentication-provider> </authentication-manager> <b:bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
which is next
@Service public class CustomUserDetailsService implements UserDetailsService{ @Autowired @Qualifier("userDaoImpl") private UserDao userDaoImpl; @Override @Transactional public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userDaoImpl.loadByUsername(username); if (user != null) return user; else throw new UsernameNotFoundException(username + " not found."); } }
This works for all users, not just the administrator.
Now there is a problem with the full functionality of the administrator account when starting the application . This is achieved by initializing the bean to start at startup, described in detail below.
@Component public class Initializer { @Autowired private HibernateTransactionManager transactionManager; @Autowired @Qualifier("userDaoImpl") private UserDao userDao; @Autowired private CredentialsManager credentialsManager; private String resetPassword = "makeItHardToGuess"; private String adminUsername = "admin"; @PostConstruct private void init() {
note that the @PostConstruct annotation @PostConstruct not guarantee that Spring has its own transactional services, so I had to manage the transaction myself. See more details.