2011-02-11 12 views
8

Tengo una aplicación simple hecha en la que puedo registrar usuarios y autenticarlos. Tengo codificadas las contraseñas y puedo autenticarlas con éxito. Estoy usando Spring 3, Spring Security 3 e Hibernate 3 en mi aplicación.Spring Security 3: problema de contraseña de salting

Ahora quiero saltear sus contraseñas con el ID del usuario, pero no puedo lograr esta funcionalidad. ¿Alguien podría ayudarme a lograrlo? He estado tratando de hacerlo por bastante tiempo pero no puedo hacerlo.

Este es el código que tengo para salar a los usuarios con su ID y autenticarlos.

xyz-security.xml

<http auto-config="true" use-expressions="true"> 
    <intercept-url pattern="/welcome.do" access="hasRole('ROLE_USER')" /> 
    <form-login login-page="/login.do" authentication-failure-url="/login.do?login_error=1"/>  
    <logout invalidate-session="true" logout-url="/logout" logout-success-url="/"/> 
</http> 

<beans:bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"> 
    <beans:property name="userDetailsService" ref="userDetailsService"/> 
</beans:bean> 

<beans:bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager"> 
    <beans:property name="providers"> 
     <beans:list> 
      <beans:ref local="daoAuthenticationProvider" /> 
     </beans:list> 
    </beans:property> 
</beans:bean> 

<authentication-manager> 
    <authentication-provider user-service-ref="userDetailsService"> 
     <password-encoder ref="passwordEncoder">     
      <salt-source ref="saltSource"/> 
      </password-encoder> 
    </authentication-provider> 
</authentication-manager> 

<!-- For hashing and salting user passwords --> 
<beans:bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder"/> 
<beans:bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource" 
    p:userPropertyToUse="id"/> 

UserDetailsAdapter.java

@Service("userDetailsAdapter") 
public class UserDetailsAdapter { 

    private Long id; 

    org.springframework.security.core.userdetails.User buildUserFromUserEntity(User userEntity) { 
     String username = userEntity.getUsername(); 
     String password = userEntity.getPassword(); 
     boolean enabled = userEntity.isEnabled(); 
     boolean accountNonExpired = true; 
     boolean credentialsNonExpired = true; 
     boolean accountNonLocked = true; 

     Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); 
     for (String authority: userEntity.getAuthorities()) { 

      authorities.add(new GrantedAuthorityImpl(authority)); 
     } 

     this.id = userEntity.getId(); 

     org.springframework.security.core.userdetails.User user = new org.springframework.security.core.userdetails.User(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities); 
     return user; 
    } 

    public Long getId() { 
     return id; 
    } 

} 

UserDetailsServiceImpl

@Service("userDetailsService") 
public class UserDetailsServiceImpl implements UserDetailsService { 

    @Autowired 
    private UserDao userDao; 

    @Autowired 
    private UserDetailsAdapter userDetailsAdapter; 

    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { 
     UserDetails userDetails = null; 
     User userEntity = userDao.findByUsername(username); 

     if (userEntity == null) { 
      throw new UsernameNotFoundException("user not found"); 
     } 
     userDetails = userDetailsAdapter.buildUserFromUserEntity(userEntity); 

     return userDetails; 
    } 
} 

UserServiceImpl

@Service 
public class UserServiceImpl implements UserService { 

    @Autowired 
    private UserDao userDao; 

    @Autowired 
    private PasswordEncoder passwordEncoder; 

    @Autowired 
    private SaltSource saltSource; 

    public User getByUsername(String username) { 
     return userDao.findByUsername(username); 
    } 

    public User getByEmail(String email) { 
     return userDao.findByEmail(email); 
    } 

    public void createUser(User user) { 
     userDao.create(user); 

     UserDetailsAdapter userDetailsAdapter = new UserDetailsAdapter(); 
     org.springframework.security.core.userdetails.User userDetails = userDetailsAdapter.buildUserFromUserEntity(user); 
     String password = userDetails.getPassword(); 
     Object salt = saltSource.getSalt(userDetails); 
     user.setPassword(passwordEncoder.encodePassword(password, salt)); 
     userDao.update(user); 

    } 

    public void updateUser(User user) { 
     userDao.update(user); 
    } 
} 

Podría alguien ayudarme a entender lo que me estoy perdiendo aquí? Muchas gracias.

+0

Podría por favor compartir su código de ejemplo? Saludos, Neha –

Respuesta

7

ReflectionSaltSource extrae una sal de la instancia de UserDetails. Pero utiliza org.springframework.security.core.userdetails.User como una implementación de UserDetails, y no tiene una propiedad llamada id (en lugar de tener esta propiedad en UserDetailsAdapter, eso no tiene sentido, ya que UserDetailsAdapter es un singleton).

Por lo tanto, es necesario crear una subclase de org.springframework.security.core.userdetails.User con id propiedad, y volverlo a partir de su UserDetailsAdapter.

+0

Gracias, funcionó :) – skip

+0

@skip: entonces probablemente deberías votar la respuesta y si estás seguro de que es correcta, entonces acéptala. – Sagar

+0

@Sagar: Eché de menos tu comentario y acabo de comprobarlo, voy a publicar mi respuesta en un momento, gracias. – skip

7

Éstos son los archivos actualizados que hacían trabajo:

UserDetailsAdapter.java

public class UserDetailsAdapter extends org.springframework.security.core.userdetails.User { 
    private final Long id; 
    public UserDetailsAdapter(User userEntity) { 

     super(userEntity.getUsername(), userEntity.getPassword(), userEntity.isEnabled(), true, true, true, toAuthorities(userEntity.getAuthorities())); 
     this.id = userEntity.getId(); 
    } 

    private static Collection<GrantedAuthority> toAuthorities(List<String> authorities) { 
     Collection<GrantedAuthority> authorityList = new ArrayList<GrantedAuthority>(); 
     for (String authority: authorities) { 
      authorityList.add(new GrantedAuthorityImpl(authority)); 
     } 
     return authorityList; 
    } 

    public Long getId() { 
     return id; 
    } 

} 

UserDetailsServiceImpl.java

@Service("userDetailsService") 
public class UserDetailsServiceImpl implements UserDetailsService { 

    @Autowired 
    private UserDao userDao; 

    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { 
     UserDetails userDetails = null; 
     User userEntity = userDao.findByUsername(username); 

     if (userEntity == null) { 
      throw new UsernameNotFoundException("user not found"); 
     } 
     userDetails = new UserDetailsAdapter(userEntity); 

     return userDetails; 
    } 
} 

UserServiceImpl.java

@Service 
public class UserServiceImpl implements UserService { 
... 
    public void createUser(User user) { 
     userDao.create(user); 

     UserDetailsAdapter userDetails = new UserDetailsAdapter(user); 
     String password = userDetails.getPassword(); 
     Object salt = saltSource.getSalt(userDetails); 
     user.setPassword(passwordEncoder.encodePassword(password, salt)); 
     userDao.update(user); 

    } 
... 
} 

Gracias :)

+0

¿Podría proporcionar un código de muestra completo? Gracias, Neha –

Cuestiones relacionadas