9

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?

4

1 回答 1

5

由于我们正在处理身份验证失败,Authentication因此事件中的对象是提交给AuthenticationManager(并且被拒绝)的对象。

在典型情况下,这将是UsernamePasswordAuthenticationToken“主要”属性是提交的用户名的地方。

支持许多不同的AuthenticationManager身份验证机制,从它的角度来看,不能保证 aUserDetailsService甚至参与身份验证。它所知道的只是身份验证令牌未被接受(出现异常)并相应地发布事件。

替代选项是自定义AuthenticationProvider正在使用的或插入AuthenticationFailureHandler(例如,如果您使用表单登录)并在那里做额外的工作。

于 2013-07-03T16:38:56.933 回答