2012-06-07 2 views
5

Cercare di capire quale sia il modo corretto di implementare l'autenticazione OpenID con Spring Security.Spring Security OpenID - UserDetailsService, AuthenticationUserDetailsService

public class OpenIDUserDetailsService implements 
    UserDetailsService, 
    AuthenticationUserDetailsService { 

    @Override 
    public UserDetails loadUserByUsername(String openId) throws 
    UsernameNotFoundException, DataAccessException { 

    // I either want user email here 
    // or immediately delegate the request to loadUserDetails 

    } 

    @Override 
    public UserDetails loadUserDetails(Authentication token) throws 
    UsernameNotFoundException { 

    // This never gets called if I throw from loadUserByUsername() 

    } 

    private MyCustomUserDetails registerUser(String openId, String email) { 
    ... 
    } 
} 

Sto considerando lo scenario in cui l'utente non è ancora registrato all'interno della mia applicazione. Per registrare l'utente, ho bisogno di conoscere il suo OpenID e l'e-mail.

Quando il provider OpenID reindirizza l'utente alla mia applicazione, viene chiamato loadUserByUsername(), ma in questo caso sono a conoscenza solo dell'openID dell'utente. Quindi, sto lanciando UsernameNotFoundException e quindi non viene mai chiamato loadUserDetails(), quindi non posso registrare l'utente.

Qual è la soluzione più comune qui? Cosa succede se restituisco qualcosa come FakePartialUserDetails da loadUserByUsername() e quindi, quando viene chiamato loadUserDetails(), registro l'utente e quindi restituisco il numero reale MyCustomUserDetails?

che sto usando Primavera di sicurezza 3.0.7.RELEASE

risposta

1

Questo è divertente, ma è riuscito a risolverlo spostando a Primavera di sicurezza 3.1.0.RELEASE.

Per lo stesso scenario, il comportamento è assolutamente diverso-loadUserByUsername() non è chiamato e loadUserDetails() si chiama invece.

+4

Questo non è corretto. In 3.1, OpenIDAuthenticationProvider ha setter sia per UserDetailsService che AuthenticationUserDetailsService e chiama loadUserByUsername o loadUserDetails a seconda del setter utilizzato. Nella 3.0.7 non esisteva un setter per AuthenticationUserDetailsService e quindi utilizzava sempre loadUserByUsername. – Ritesh

0

ho risolto la stessa situazione mediante l'attuazione di

AuthenticationUserDetailsService<OpenIDAuthenticationToken> 

nel mio UserDetailsService.

public class OpenIdUserDetailsService implements UserDetailsService, 
    AuthenticationUserDetailsService<OpenIDAuthenticationToken> { 

@Autowired(required = true) 
@Qualifier(value = "jdbcUserDetailsService") 
private UserDetailsService localUserDetailsService; 

/** 
* @return the localUserDetailsService 
*/ 
public UserDetailsService getLocalUserDetailsService() { 
    return localUserDetailsService; 
} 

/** 
* @param localUserDetailsService 
*   the localUserDetailsService to set 
*/ 
public void setLocalUserDetailsService(
     UserDetailsService localUserDetailsService) { 
    this.localUserDetailsService = localUserDetailsService; 
} 

@Override 
public UserDetails loadUserDetails(OpenIDAuthenticationToken token) 
     throws UsernameNotFoundException { 
    String email = getEmail(token); 
    return loadUserByUsername(email); 
} 

@Override 
public UserDetails loadUserByUsername(String username) 
     throws UsernameNotFoundException { 
    return localUserDetailsService.loadUserByUsername(username); 
} 

private String getEmail(OpenIDAuthenticationToken token) { 
    for (OpenIDAttribute attribute : token.getAttributes()) { 
     if (attribute.getName().equals("email")) { 
      return attribute.getValues().get(0); 
     } 
    } 
    return null; 
} 

} 

Basta fare in modo di utilizzare al di sopra di servizio come l'UserDetailsService durante la configurazione OpenID-modulo. Inoltre, configura lo scambio di attributi per l'attributo 'email' durante la configurazione di openid. Il messaggio di posta elettronica restituito dopo che l'autenticazione ha avuto esito positivo può quindi essere recuperato da "OpenIDAuthenticationToken" che alla fine viene passato come parametro per caricare la funzione nomeUtenteByUsername.

Se l'utente ha effettuato la registrazione con tale messaggio, l'autenticazione è completa. Altrimenti puoi suggerire all'utente di registrarsi con quell'e-mail o mostrare la pagina di errore di accesso.

+0

Ritesh risponde alla ragione effettiva per OP (commento per risposta accettata!) – manikanta