2013-01-02 12 views
7

Uso Spring Security nell'app MVC della mia primavera.Spring Security utilizzando sia il nome utente che l'e-mail

JdbcUserDetailsManager viene inizializzato con la seguente query per l'autenticazione:

select username, password, enabled from user where username = ? 

E le autorità vengono caricati qui:

select u.username, a.authority from user u join authority a on u.userId = a.userId where username = ? 

Vorrei fare in modo che gli utenti possano effettuare il login sia con nome utente e la e-mail. C'è un modo per modificare queste due query per raggiungere questo? O c'è una soluzione ancora migliore?

risposta

4

Purtroppo non esiste un modo semplice per farlo cambiando le query. Il problema è che la sicurezza la primavera si aspetta che gli utenti-by-nome utente-query e le autorità-by-nome utente-query hanno un unico parametro (username), quindi se la query contiene due parametri come

username = ? or email = ? 

la query non riuscirà .

cosa si può fare, è quello di implementare il proprio UserDetailsService che eseguirà la query (o query) per cercare utente per utente o email e quindi utilizzare questa implementazione come l'autenticazione del provider nella configurazione della sicurezza primavera come

<authentication-manager> 
    <authentication-provider user-service-ref='myUserDetailsService'/> 
    </authentication-manager> 

    <beans:bean id="myUserDetailsService" class="xxx.yyy.UserDetailsServiceImpl"> 
    </beans:bean> 
+0

Ho esaminato la classe ma ho un po 'di problemi a capire quali metodi dovrei sovrascrivere. Qualche indicazione? – tumanov

+1

Penso di vederlo ora: loadUserByUsername (String username) – tumanov

1

È possibile definire query personalizzate nel tag <jdbc-user-service> negli attributi users-by-username-query e authorities-by-username-query rispettivamente.

<jdbc-user-service data-source-ref="" users-by-username-query="" authorities-by-username-query=""/> 

Aggiornamento

È possibile creare una classe che implementa org.springframework.security.core.userdetails.UserDetailsService e configurare l'applicazione per utilizzarlo come fonte di autenticazione. All'interno del servizio personalizzato UserDetails è possibile eseguire query necessarie per ottenere utenti dal database.

+0

Questo è esattamente quello che ho già fatto e ho incluso entrambi nella mia domanda. Il problema è che devo personalizzarli per includere sia il nome utente che l'email. – tumanov

+0

Non hai menzionato che sai come configurarli. E tu stai chiedendo "C'è un modo per modificare queste due domande per raggiungere quello?". –

+0

Ad ogni modo ho aggiornato la mia risposta. –

2

Se ho capito bene, il problema è che si vuole cercare il nome utente inserito dall'utente in due colonne DB diverse.

Certo, puoi farlo personalizzando UserDetailsService.

public class CustomJdbcDaoImpl extends JdbcDaoImpl { 

    @Override 
    protected List<GrantedAuthority> loadUserAuthorities(String username) { 
    return getJdbcTemplate().query(getAuthoritiesByUsernameQuery(), new String[] {username, username}, new RowMapper<GrantedAuthority>() { 
      public GrantedAuthority mapRow(ResultSet rs, int rowNum) throws SQLException { 
       ....... 
      } 
     }); 
    } 

    @Override 
    protected List<UserDetails> loadUsersByUsername(String username) { 
     return getJdbcTemplate().query(getUsersByUsernameQuery(), new String[] {username, username}, new RowMapper<UserDetails>() { 
      public UserDetails mapRow(ResultSet rs, int rowNum) throws SQLException { 
       ....... 
      } 
     }); 
} 

La configurazione del bean per questa classe sarà simile a questa.

<beans:bean id="customUserDetailsService" class="com.xxx.CustomJdbcDaoImpl"> 
    <beans:property name="dataSource" ref="dataSource"/> 
    <beans:property name="usersByUsernameQuery"> 
     <beans:value> YOUR_QUERY_HERE</beans:value> 
    </beans:property> 
    <beans:property name="authoritiesByUsernameQuery"> 
     <beans:value> YOUR_QUERY_HERE</beans:value> 
    </beans:property> 
</beans:bean> 

Le query avrà un aspetto simile a questo

select username, password, enabled from user where (username = ? or email = ?) 
select u.username, a.authority from user u join authority a on u.userId = a.userId where (username = ? or email = ?) 
2

Ho avuto lo stesso problema, e dopo aver provato con un sacco di domande diverse, con procedure ... I trovato che questo funziona:

public void configAuthentication(AuthenticationManagerBuilder auth) 
     throws Exception { 
    // Codificación del hash 
    PasswordEncoder pe = new BCryptPasswordEncoder(); 

    String userByMailQuery = "SELECT mail, password, enabled FROM user_ WHERE mail = ?;"; 
    String userByUsernameQuery = "SELECT mail, password, enabled FROM user_ WHERE username=?"; 
    String roleByMailQuery = "SELECT mail, authority FROM role WHERE mail =?;"; 

    auth.jdbcAuthentication().dataSource(dataSource).passwordEncoder(pe) 
      .usersByUsernameQuery(userByMailQuery) 
      .authoritiesByUsernameQuery(roleByMailQuery); 

    auth.jdbcAuthentication().dataSource(dataSource).passwordEncoder(pe) 
      .usersByUsernameQuery(userByUsernameQuery) 
      .authoritiesByUsernameQuery(roleByMailQuery); 

} 

Il suo ju st ripete la configurazione con le due query.

Problemi correlati