1. Overview
The example to create a custom database-backend UserDetailsService for authentication with Spring Security is on Github.
2. UserDetailsService
The UserDetailsService interface is used to retrieve user-related data. It has one method named loadUserByUsername() which finds a user entity based on the username and 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.
3. The User Model
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
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(nullable = false, unique = true)
private String username;
private String password;
//standard getters and setters
}
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:
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}
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);
}
}
The MyUserPrincipal class is defined as follows:
public class MyUserPrincipal implements UserDetails {
private User user;
public MyUserPrincipal(User user) {
this.user = user;
}
//...
}
6. Spring Configuration
6.1. Annotation Configuration
Using Spring annotations, we will define the UserDetailsService bean, and set it as a property of the authenticationProvider bean, which we inject into the authenticationManager:
@Autowired
private MyUserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.authenticationProvider(authenticationProvider());
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider
= new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(encoder());
return authProvider;
}
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder(11);
}
6.2. XML Configuration
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:authentication-manager>
<security:authentication-provider
user-service-ref="myUserDetailsService" >
<security:password-encoder ref="passwordEncoder">
</security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
<bean id="passwordEncoder"
class="org.springframework.security
.crypto.bcrypt.BCryptPasswordEncoder">
<constructor-arg value="11"/>
</bean>
-
Previous
Spring Security - Retrieve User Information -
Next
Spring Security Expressions - hasRole Example