2013-07-03 2 views
6

O mi manca qualcosa, o questo è come funziona ...
Vale a dire, ho implementato UserDetailsService, e sub-classificati (AppUser sotto) classe di utilità primavera User, (che implementa UserDetails). Se è importante, è più o meno così:Ritorni sicurezza di sicurezza Stringa come entità principale invece di UserDetails in caso di accesso non riuscito?

@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; 
} 

Poi ho cercato di implementare conto di bloccaggio utilizzando questo approccio:

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 ? 
    // ... 
} 
} 

Tuttavia, mi sono imbattuto in java.lang.ClassCastException durante il tentativo di ottenere l'oggetto principale della argomento evento fornito (l'oggetto principale era di tipo String). Voglio dire, OK, posso semplicemente caricare il mio SystemUser per nome utente, per risolvere il problema, ma non mi aspettavo questo ...
Penso che anche la documentazione di origine afferma che getPrincipal() dovrebbe restituire l'istanza UserDetails, per questo scenario.
Pensieri?

risposta

5

Poiché si tratta di un errore di autenticazione, l'oggetto Authentication nell'evento è quello che è stato inviato allo AuthenticationManager (e che è stato rifiutato).

In uno scenario tipico, questo sarebbe un UsernamePasswordAuthenticationToken dove la proprietà "principal" è il nome utente inviato.

Il numero AuthenticationManager supporta molti diversi meccanismi di autenticazione e, dal suo punto di vista, non è garantito che un UserDetailsService sia coinvolto anche nell'autenticazione. Tutto ciò che sa è che il token di autenticazione non è stato accettato (c'è stata un'eccezione) e pubblica l'evento di conseguenza.

Le opzioni alternative sono personalizzare il AuthenticationProvider in uso o collegare un AuthenticationFailureHandler (se si utilizza il login modulo, ad esempio) e fare il lavoro extra in là.

+0

Quindi, questo è in realtà il modo in cui dovrebbe essere ...? Sto già usando 'AuthenticationSuccessHandler' per il reset del contatore, non posso dire se questo è l'approccio giusto, non mi è venuto in mente di provare con' AuthenticationFailureHandler'. – Less

+0

Sì, è così che dovrebbe essere. L'evento dice "questa è la richiesta di autenticazione non riuscita" e la richiesta di autenticazione contiene solo un identificatore di stringa per l'utente. –