Either I'm missing something, or this is how it works...
Namely, I implemented UserDetailsService
, and sub-classed (AppUser
below) spring utility class User
, (that implements UserDetails
). If it matters, it goes something like this:
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
// try loading user by its name
SystemUser user = null;
try {
user = this.sysUserService.getByUsername(username);
if(user == null)
throw new UsernameNotFoundException("User not found!");
}
catch(Exception e) {
throw new DataRetrievalFailureException(
"Could not load user with username: " + username);
}
// load user rights, and create UserDetails instance
UserDetails res = new AppUser(user, getUserAuthorities(user));
return res;
}
Then I tried to implement account locking using this approach:
public class LoginFailureEventListenter implements
ApplicationListener<AuthenticationFailureBadCredentialsEvent> {
// rest omitted for brevity
@Override
public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent event) {
// ...
SystemUser user = ((AppUser)event.getAuthentication().getPrincipal()).getSystemUser();
// cast exception - how is it possible to obtain String
// instead of UserDetails object here ?
// ...
}
}
However, I ran into java.lang.ClassCastException
while trying to get the principal object from the supplied event argument (principal object was of type String
). I mean, OK - I can just load my SystemUser
by username again, to solve the problem, but I did not expect this...
I think that even the source documentation states that getPrincipal()
should return UserDetails
instance, for this scenario.
Thoughts?