2012-06-07 28 views
5

Tratando de entender cuál es la forma correcta de implementar la autenticación 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) { 
    ... 
    } 
} 

Estoy considerando el escenario cuando el usuario aún no está registrado en mi aplicación. Para registrar al usuario, necesito saber su OpenID y correo electrónico.

Cuando el proveedor de OpenID redirecciona al usuario a mi aplicación, se llama al loadUserByUsername(), pero en este caso solo conozco el OpenID del usuario. Por lo tanto, estoy lanzando UsernameNotFoundException y luego loadUserDetails() nunca se llama, por lo que no puedo registrar usuario.

¿Cuál es la solución común aquí? ¿Qué sucede si devuelvo algo como FakePartialUserDetails de loadUserByUsername() y luego, cuando se llama al loadUserDetails(), registro al usuario y luego devuelvo el MyCustomUserDetails real?

estoy usando Spring Security 3.0.7.RELEASE

Respuesta

1

Eso es gracioso, pero se las arregló para resolverlo moviendo a Spring Security 3.1.0.RELEASE.

Por el mismo escenario, el comportamiento es absolutamente diferente-loadUserByUsername() no se llama y loadUserDetails() se llama en su lugar.

+4

Esto no es correcto. En 3.1, OpenIDAuthenticationProvider tiene configuradores para UserDetailsService y AuthenticationUserDetailsService y llama a loadUserByUsername o loadUserDetails dependiendo del setter que se use. En 3.0.7, no existía un setter para AuthenticationUserDetailsService y siempre usaba loadUserByUsername. – Ritesh

0

Solucioné la misma situación mediante la implementación de

AuthenticationUserDetailsService<OpenIDAuthenticationToken> 

en mi 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; 
} 

} 

Solo asegúrese de utilizar el servicio anterior como UserDetailsService mientras configura openid-form. Además, configure el intercambio de atributos para el atributo 'email' mientras configura openid. El correo electrónico devuelto después de la autenticación exitosa se puede obtener de 'OpenIDAuthenticationToken', que finalmente pasa como parámetro a la función loadUserByUsername.

Si tiene un usuario registrado con ese correo electrónico, la autenticación está completa. De lo contrario, puede sugerir al usuario que se registre en ese correo electrónico o que muestre la página de error de inicio de sesión.

+0

Razón real para OP es respondida por Ritesh (¡comentario para la respuesta aceptada!) – manikanta

Cuestiones relacionadas