2011-10-05 22 views
50

¿Hay algún tutorial o alguien tiene sugerencias sobre cómo hacer lo siguiente con Spring-Security?Spring Security Autenticación personalizada y codificación de contraseña

Tarea:

que necesito para obtener la sal de mi base de datos para el nombre de usuario de autenticación y lo utilizan para cifrar la contraseña proporcionada (desde la página de inicio de sesión) para compararla con la contraseña cifrada almacenada (también conocido como autenticar el usuario).

información adicional:

que utilizan una estructura de base de datos personalizada. Se crea un objeto UserDetails a través de un UserDetailsService personalizado que a su vez usa un DAOProvider personalizado para obtener la información de la base de datos.

mi archivo security.xml hasta ahora:

<authentication-manager> 
    <authentication-provider user-service-ref="userDetailsService"> 
    </authentication-provider> 
</authentication-manager> 

ahora supongo que necesitaré

 <password-encoder hash="sha" /> 

pero ¿qué más? ¿Cómo digo a la seguridad de primavera que use la sal proporcionada por la base de datos para codificar la contraseña?


edición:

encontré This SO después de ser informatative pero no suficiente: Si defino una fuente de sal en mi XML para ser utilizado por el codificador contraseña, así:

 <password-encoder ref="passwordEncoder">     
      <salt-source ref="saltSource"/> 
     </password-encoder> 

Tendré que escribir un SaltSource personalizado para usar mi sal personalizada. Pero eso no se encuentra dentro del objeto UserDetails. Así que ...

Alternativa 1:

¿Puedo utilizar una implementación personalizada de DetallesUsuario que podría entonces tener la propiedad de la sal?

<beans:bean id="saltSource" class="path.to.MySaltSource" 
    p:userPropertyToUse="salt"/> 

y

@Service("userDetailsService") 
public class UserDetailsServiceImpl implements UserDetailsService { 
    public UserDetails loadUserByUsername(String username) 
      throws UsernameNotFoundException, DataAccessException { 

     // ... 
     return buildUserFromAccount(account); 
    } 

    @Transactional(readOnly = true) 

    UserDetailsImpl buildUserFromAccount(Account account){ 

     // ... build User object that contains salt property 
} 

encargo de clase de usuario:

public class UserDetailsImpl extends User{ 

    // ... 

    private String salt; 

    public String getSalt() { return salt; } 

    public void setSalt(String salt) { this.salt = salt; } 
} 

security.xml:

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

<beans:bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource" p:userPropertyToUse="salt"/> 


Alternativa 2:

De lo contrario tendría que inyectar mi accountDAO en el SaltSource para extraer la sal para un determinado userName de la base de datos.

PERO: ¿Cómo llama Spring Security al SaltSource?Siempre con saltSource.getSalt(userDetails)?

Entonces solo tendría que asegurarme de que mi SaltSource usa userDetails.accountName en mi accountDAO para recuperar la sal.


Edit2:

acabo de enterar que mi enfoque es .. legado .. :(Así que supongo que sólo tiene que utilizar el StandardPasswordEncoder (que todavía tengo que encontrar la manera de utilizar exactamente)

BTW: Implementé la primera opción con una clase UserDetails personalizada que ampliaba la clase User y simplemente agregaba una propiedad salt que luego se pasaba a SaltSource como userPropertyToUse tal como se propuso en la publicación SO mencionada en Editar 1 ...


Datos 3:

Acabo StandardPasswordEncoder el trabajo, así que voy a dejar algunos consejos aquí:

Uso del StandardPasswordEncoder para la autenticación:

<beans:bean id="encoder" 
    class="org.springframework.security.crypto.password.StandardPasswordEncoder"> 
</beans:bean> 


<authentication-manager> 
    <authentication-provider user-service-ref="userDetailsService"> 
     <password-encoder ref="encoder" />   
    </authentication-provider> 
</authentication-manager> 

tal fin es necesario módulo spring-security-crypto en la versión 3.1.0.RC? por lo que sé. No se pudo encontrar ningún repositorio que tenga un 3.0. versión (aunque en alguna parte tenía las versiones enumeradas que incluían 3.0.6 y así sucesivamente). También la documentación habla sobre la seguridad de la primavera 3.1, así que pensé, iré con eso.

Al crear un usuario (para mí sólo un administrador puede hacer eso), sólo tiene que utilizar

 StandardPasswordEncoder encoder = new StandardPasswordEncoder(); 
     String result = encoder.encode(password); 

y he terminado.

La seguridad de primavera creará aleatoriamente una sal y la agregará a la cadena de contraseña antes de almacenarla en la base de datos para que ya no se necesite ninguna columna de sal.

Uno puede sin embargo también proporcionan una sal global como un argumento del constructor (new StandardPasswordEncoder("12345");), pero yo no sabía cómo configurar mi configuración de seguridad para recuperar ese valor de un grano en lugar de suministrar una cadena estática con <constructor-arg name="secret" value "12345" />. Pero no sé cuánto se necesita de todos modos.

Respuesta

34

Voy a marcar esto como respondí, como he resuelto mi problema y se dieron más comentarios o respuestas:

Edición 1 - Alternativa 1 responde a la pregunta original

PERO que tenía aprender que el salado de contraseñas personalizado es un enfoque heredado que ya no es necesario en Spring Security 3.1, como lo describo en

Editar 3 donde dejé algunos consejos sobre cómo use el StandardPasswordEncoder para Sales automatizadas que se almacenan con la contraseña.

+1

Tu publicación realmente me ayudó, tuve un problema muy similar. +1 para la auto-resolución ^^ – user1431729

+4

Sugeriría BCryptPasswordEncoder en lugar de StandardPasswordEncoder. BCryptPasswordEncoder es una mejor opción tanto en términos de seguridad como de interoperabilidad con otros lenguajes – Farm

0

Para recuperar la sal de un grano mundial, utilizan el lenguaje Expresión primavera o SpEL.

<beans:bean id="encoder" 
     class="org.springframework.security.crypto.password.StandardPasswordEncoder"> 
    <constructor-arg value="#{someotherBean.somePropertyWithAGetterMethod"/> 
</beans:bean> 
Cuestiones relacionadas