Authentication With A Database-Backed UserDetailsService
Authentication With A Database-Backed UserDetailsService
Spring Security:
Authentication with a Database-
backed UserDetailsService
Spring Security
Written by: Loredana Crusoveanu
Authentication
1. Overview
In this article, we will show how to create a custom database-backed UserDetailsService for
authentication with Spring Security.
2. UserDetailsService
The UserDetailsService interface is used to retrieve user-related data. It has one method named
loadUserByUsername() which can be overridden to customize the process of finding the user.
It is used by the DaoAuthenticationProvider to load details about the user during authentication.
For storing users, we will create a User entity that is mapped to a database table, with the following
attributes:
@Entity
public class User {
@Id
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
4. Retrieving a User
For the purpose of retrieving a user associated with a username, we will create a DAO class using Spring
Data by extending the JpaRepository interface:
5. The UserDetailsService
In order to provide our own user service, we will need to implement the UserDetailsService interface.
We'll create a class called MyUserDetailsService that overrides the method loadUserByUsername() of the
interface.
In this method, we retrieve the User object using the DAO, and if it exists, wrap it into a MyUserPrincipal
object, which implements UserDetails, and returns it:
@Service
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException(username);
}
return new MyUserPrincipal(user);
}
}
6. Spring Configuration
We will demonstrate both types of Spring configurations: XML and annotation-based, which are necessary
in order to use our custom UserDetailsService implementation.
All we need to do to enable our custom UserDetailsService is add it to our application context as a bean.
Since we configured our class with the @Service annotation, the application will automatically detect it
during component-scan, and it will create a bean out of this class. Therefore, there isn't anything else we
need to do here.
Alternatively, we can:
configure it in the authenticationManager using the AuthenticationManagerBuilder#userDetailsService
method
set it as a property in a custom authenticationProvider bean, and then inject that using the
AuthenticationManagerBuilder# authenticationProvider function
On the other hand, for the XML configuration we need to define a bean with type MyUserDetailsService,
and inject it into Spring's authentication-provider bean:
<bean id="myUserDetailsService"
class="org.baeldung.security.MyUserDetailsService"/>
<security:authenticationmanager>
<security:authenticationprovider
userserviceref="myUserDetailsService" >
<security:passwordencoder ref="passwordEncoder">
</security:passwordencoder>
</security:authenticationprovider>
</security:authenticationmanager>
<bean id="passwordEncoder"
class="org.springframework.security
.crypto.bcrypt.BCryptPasswordEncoder">
.crypto.bcrypt.BCryptPasswordEncoder">
<constructorarg value="11"/>
</bean>
The AuthenticationManagerBuilder offers one other method to configure JDBC-based authentication in our
application.
8. Conclusion
To sum up, in this article we've shown how to create a custom Spring-based UserDetailsService backed
by persistent data.
The implementation can be found in the GitHub project – this is a Maven based project, so it should be
easy to import and run as it is.
Learn the basics of securing a REST
API with Spring