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?
Since we are dealing with an authentication failure, the Authentication
object in the event is the one which was submitted to the AuthenticationManager
(and which was rejected).
In a typical scenario this would be a UsernamePasswordAuthenticationToken
where the "principal" property is the submitted username.
The AuthenticationManager
supports lots of different authentication mechanisms and, from its perspective, there's no guarantee that a UserDetailsService
is even involved in the authentication. All it knows is that the authentication token was not accepted (there was an exception) and it publishes the event accordingly.
Alternative options are to customize the AuthenticationProvider
in use or plug in an AuthenticationFailureHandler
(if you're using form-login, for example) and do the extra work in there.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.