We can extend Spring Security by providing a custom implementation for UserDetailsService. The following example shows a hardcoded in-memory implementation:
@Service
public class InMemoryUserDetailsService implements UserDetailsService {
static List < CustomizedUserDetails > inMemoryUserList = new ArrayList < > ();
static {
inMemoryUserList.add(new CustomizedUserDetails(1 L, "mastering-spring-inmemory", "{noop}dummy", "ROLE_USER_2"));
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional < CustomizedUserDetails > findFirst = inMemoryUserList.stream()
.filter(user - > user.getUsername().equals(username)).findFirst();
if (!findFirst.isPresent()) {
throw new UsernameNotFoundException(String.format("USER_NOT_FOUND '%s'.", username));
}
return findFirst.get();
}
}
We are creating an in-memory user list—inMemoryUserList. Now, loadUserByUsername checks the username against the in-memory list, and returns an instance of CustomizedUserDetails—an implementation of UserDetails. A few details about CustomizedUserDetails are shown here:
public class CustomizedUserDetails implements UserDetails {
private final Long id;
private final String username;
private final String password;
private final Collection << ? extends GrantedAuthority > authorities;
public CustomizedUserDetails(Long id, String username, String password, String role) {
//Constructor
}
We can also integrate with a database, and implement UserDetailsService. The following example shows a UserDetailsService implementation talking to a Spring data JPA-configured userRepository:
@Service
public class DatabaseUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException(String.format("USER_NOT_FOUND '%s'.", username));
}
return new CustomizedUserDetails(user.getId(), user.getUsername(), user.getPassword(), user.getRole());
}
}