2013-01-13 12 views
13

Ho implementato la funzionalità di cambio password utilizzando la sicurezza di primavera ma (principal (UserDetails)) .getPassword()) restituisce null per l'utente connesso.UserDetails getPassword restituisce null in spring security 3.1. Come ottenere la password dell'utente attualmente connesso?

Se ricordo bene, questo funzionava in precedenza in 3.0. È stato modificato in 3.1 in modo che la password corrente dell'utente connesso non possa essere recuperata?

Nel seguente codice sto controllando la password corrente digitata nella password utente dalla pagina web. Sto quindi controllando se la password dell'utente connesso corrisponde alla password digitata. Se lo fa allora voglio impostare oldPasswordMatchNewPassword = true.

Come si implementa questa funzionalità?

@RequestMapping(value = "/account/changePassword.do", method = RequestMethod.POST) 
    public String submitChangePasswordPage(
      @RequestParam("oldpassword") String oldPassword, 
      @RequestParam("password") String newPassword) { 
     Object principal = SecurityContextHolder.getContext() 
       .getAuthentication().getPrincipal(); 
     String username = principal.toString(); 
     if (principal instanceof UserDetails) { 
      username = ((UserDetails) principal).getUsername(); 
      System.out.println("username: " + username); 
      System.out.println("password: " 
        + ((UserDetails) principal).getPassword()); 
      if (((UserDetails) principal).getPassword() != null) { 
       if (((UserDetails) principal).getPassword().equals(oldPassword)) { 
        oldPasswordMatchNewPassword = true; 
       } 
      } 
     } 
    if (oldPasswordMatchNewPassword == true) { 
     logger.info("Old password matches new password. Password will be updated."); 
     changePasswordDao.changePassword(username, newPassword); 
     SecurityContextHolder.clearContext(); 
     return "redirect:home.do"; 
    } else { 
     logger.info("Old password did not match new password. Password will be not be updated."); 
     return null; 
    } 
} 

Ho messo un paio di sysout() s in modo che possa vedere i valori restituiti. Per il principal ((UserDetails)) .getUsername() Riesco a vedere l'utente loggato corretto. (principal (UserDetails)) .getPassword() restituisce null.

Come ottengo ((UserDetails) principal) .getPassword() questo valore?

Grazie in anticipo!

risposta

25

Ho usato questo blocco di codice (erase-credentials = "false") per risolvere questo problema. Non so se questa è una soluzione elegante, ma risolto il mio problema:

<authentication-manager alias="authenticationManager" erase-credentials="false"> 
    <!-- authentication-provider user-service-ref="userService" --> 
    <authentication-provider> 
     <jdbc-user-service data-source-ref="dataSource" /> 
    </authentication-provider> 
</authentication-manager> 
6

Sì, questo è cambiato nella versione 3.1. Le credenziali vengono cancellate dopo l'autenticazione di successo per impostazione predefinita. È possibile impostare eraseCredentialsAfterAuthentication su false su ProviderManager per impedirlo. Vedere i dettagli qui: http://static.springsource.org/spring-security/site/docs/3.2.x/reference/core-services.html#core-services-erasing-credentials

+0

Questo ha senso. Quindi qual è la migliore pratica per farlo? Non voglio disattivare eraseCredentialsAfterAuthentication perché potrebbe rappresentare un rischio per la sicurezza. Puoi aiutarmi a capirlo? – texasdude11

2

Dato che la password non viene mantenuta in memoria dopo che l'utente è stato autenticato (generalmente una buona cosa), si avrebbe bisogno di esplicitamente ricaricalo per usarlo. Una strategia alternativa e più flessibile è quello di iniettare un'istanza del AuthenticationManager e l'uso che direttamente:

String name = SecurityContextHolder.getContext().getAuthentication(); 

try { 
    authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(name, oldPassword)); 
    // Update password here with your dao 
} catch (AuthenticationException e) { 
    // Old password was wrong 
} 

in questo modo non c'è bisogno di preoccuparsi di cose come le strategie da password di codifica. Si noti che non si devono memorizzare password in testo normale. Dovrebbero essere sottoposti a hash utilizzando bcrypt or something similar.

Problemi correlati