2009-07-02 27 views
17

En una pila de aplicaciones Java con Spring & Hibernate (JPA) en la Capa de acceso a datos, cuáles son buenos métodos para aplicar la encriptación de contraseña (con suerte utilizando anotaciones) y dónde obtener más información sobre cómo hacerlo (tutorial, etc.)?Encriptación de contraseña con Spring/Hibernate - Jasypt u otra cosa?

Se entiende que usaría un algoritmo compatible con JCA para encriptar las contraseñas, pero preferiría no tener que implementar la lógica del contenedor si hay una manera fácil.

Estaba mirando a Jasypt, y estaba a) preguntándome si esa es una buena opción y cómo hacerlo yb) qué más está usando la gente para esto. Si alguien está usando Jasypt o una alternativa, los detalles de tu experiencia serían geniales.

+0

Siempre he almacena el hash de la contraseña en lugar de la contraseña real. De esta forma, aún puede verificarlo, pero no tiene la responsabilidad de almacenarlo. – Jesse

+1

Correcto, eso es exactamente lo que quiero hacer, simplemente tratar de encontrar una biblioteca que ayude con el hash + la consulta sobre una capa ORM. – stevedbrown

Respuesta

7

Java tiene todas las bibliotecas necesarias ya provistas para usted. Simplemente cree un método de utilidad que implementa hash con una sal como se describe en OWASP.

Si usted realmente no quiere ser dueño de ese código y no le importa una dependencia adicional, parece que la biblioteca Shiro (anteriormente JSecurity) tiene una implementation de lo que está descrito por OWASP.

También parece que la biblioteca JASYPT que ha mencionado tiene un similar utility.

Me doy cuenta de que esta respuesta no menciona a Spring ni a Hibernate, pero no estoy seguro de cómo espera utilizarlas en este escenario.

0

Solo uso algo similar a SHA-256(username + ":" + password + ":" + salt) y lo almaceno en la base de datos en una columna de 64 caracteres llamada passwd.

Wikipedia dice, en relación con las sales: "Los datos de sal complican los ataques de diccionario que utilizan encriptación previa de entradas de diccionario: cada bit de sal utilizado duplica la cantidad de almacenamiento y cálculo requeridos ... Para mayor seguridad, el valor de sal se mantiene en secreto, separado de la base de datos de contraseñas. Esto proporciona una ventaja cuando se roba una base de datos, pero la sal no lo es ".

Para autenticarse, obtenga el usuario de la base de datos con el nombre de usuario proporcionado, luego genere el mismo hash usando la contraseña proporcionada a través de su intento de inicio de sesión y compárelo con la base de datos. También agregue algún límite de velocidad para intentos de inicio de sesión (por ejemplo, 5 por período de 5 minutos). Si el usuario olvida su contraseña, NUNCA envíeles la contraseña por correo electrónico (ya que no la tendrá almacenada), ni les envíe una nueva contraseña generada por correo electrónico, pero envíeles un enlace para cambiar esa contraseña con una clave de cambio de contraseña/nonce/salt en la URL con la que puede verificar.

+0

He editado mi pregunta: no estaba buscando el algoritmo, sino una forma estándar (es decir, implementada por la biblioteca) de utilizar los algoritmos JCA con una pila Spring/Hibernate. – stevedbrown

+1

¿Desea realmente algo así como la anotación @Password("SHA-256") en un campo en su modelo de cuenta de usuario y para que su marco de trabajo maneje automáticamente la validación en segundo plano? En algún punto, comienzas a pedirle a un marco que sea demasiado específico en términos de funcionalidad y que sacrifique la flexibilidad. – JeeBee

2

MD5 o SHA-256 estarían bien, aunque MD5 es crackable ahora.

Quizás entendí mal el problema, pero debería ser simplemente comparar las contraseñas hash.

En hibernate, solo almacene como una cadena. En el lado de la validación, tenga un método como:

public validate(String user, String pass) 
{ 
    if(getUser(user).getPass().equals(getHash(pass))) 
     return true; 
    return false; 
} 
+1

El mismo comentario, no estaba buscando una arquitectura o algoritmo para usar, solo cómo la gente realmente lo hace. – stevedbrown

+0

¿Es esto más lo que estás buscando? http://www.evolt.org/node/60122 – Jesse

+0

Eso describe lo que estoy haciendo ahora. Me preguntaba si hay alguna manera de anotar las propiedades de hibernación o algo para hacer esto automáticamente. Parece más limpio. – stevedbrown

5

Puede usar Jasypt with Hibernate para cifrar o modificar sus propiedades sobre la marcha si eso es lo que está buscando. El algoritmo real para calcular compendios (hash) es bastante simple usando la JCE si también quieres hacer tu propia versión.

+0

No creo que el enfoque JASYPT con Hibernate sea ideal para las contraseñas ya que es posible descifrar el valor. Las contraseñas deben ser de seguridad con un resumen unidireccional. – laz

+0

JASYPT admite esto - http://www.jasypt.org/howtoencryptuserpasswords.html. – stevedbrown

+0

Lo vi, pero no parece que la integración de Hibernate que ofrecen lo aproveche. La integración de Hibernate es solo para encriptar/descifrar, no para digerir en un solo sentido. – laz

2

No parece ser una forma específica de Hibernate hacerlo con Jasypt, pero se puede establecer un encriptador contraseña en primavera:

<!-- 
    Set up string digester here so we can configure it for more pools if it's a problem... 
    --> 
    <bean id="stringDigester" class="org.jasypt.digest.PooledStringDigester"> 
    <!-- same settings as StrongPasswordGenerator --> 
    <property name="poolSize" value="2"/> 
    <property name="algorithm" value="SHA-256"/> 
    <property name="iterations" value="100000"/> 
    <property name="saltGenerator"> 
     <bean class="org.jasypt.salt.RandomSaltGenerator"/> 
    </property> 
    <property name="saltSizeBytes" value="16"/> 
    </bean> 

    <!-- ...and then we only have to deal with the passwordEncryptor interface in code. --> 
    <bean id="passwordEncryptor" class="com.myproject.util.StringPasswordEncryptor"> 
    <property name="stringDigester" ref="stringDigester"/> 
    </bean> 

Después de eso, se llaman context.getBean ("passwordEncryptor ") para obtener el encriptador, y luego llamar a encryptPassword() o checkPassword().

Cuestiones relacionadas