Pregunta

Estoy creando un sitio web PHP que involucra a los usuarios registrarse, y me pregunto sobre las mejores prácticas para los códigos de confirmación "e-mail".

Los nuevos usuarios deben confirmar sus direcciones de correo electrónico - hago esto mediante la generación de un código y enviarlo al usuario en un correo electrónico, que luego se puede utilizar para activar su cuenta. En lugar de almacenar esta clave en una base de datos, estoy usando un poco de solución práctica: el código es el resultado de:

md5("xxxxxxxxx".$username."xxxxxxxxxxx".$timestamp."xxxxxxxxx");

Donde $ sello de tiempo se refiere al tiempo fácil de creación. En conjunto me quedé bastante satisfecho con esto, pero luego me puse a pensar, ¿es lo suficientemente seguro? Y qué decir de la posibilidad de colisiones? Y también necesito para generar códigos para restablecer contraseña, etc. Si he usado una metodología similar, una colisión podría dar lugar a un usuario sin darse cuenta de restablecer la contraseña de otro usuario. Y eso no es bueno.

Entonces, ¿cómo haces estas cosas? Mi pensamiento era una tabla con el siguiente formato:

codePK (int, a-I), userID (int), type (int), code (varchar 32), date (timestamp)

Donde 'tipo' sería 1, 2 o 3 significado de "activación", "cambio de correo electrónico" o "restablecimiento de contraseña". ¿Es esta una buena manera de hacerlo? ¿Tiene una mejor manera?

Usando un método similar al anterior, podría eliminar automáticamente algo más de dos días sin usar cron? Mi anfitrión (nearlyfreespeech.net) no los admite. Si es posible me gustaría evitar tener un trabajo programado en un host externo, que wget es un script que borra las cosas, ya que eso es sólo desordenado = P.

Gracias!
Mala

Actualización:
Para aclarar: Me he dado cuenta de la única manera de ir de forma segura acerca de esta tarea es mediante el uso de una base de datos, que es lo que la función original estaba tratando de evitar. Mi pregunta es sobre cómo la tabla (o tablas?) Debe ser estructurado. Alguien me sugirió que acabar con codePK y simplemente hacer que el código de una PK. Así que en resumen, mi pregunta es: ¿es esto lo que hace

¿Fue útil?

Solución

Cuando necesito este tipo de trucos es normalmente de una de dos razones, ambos mencionados por usted:

  1. Como clave utilizada para mensajes de correo electrónico de verificación enviado al usuario
  2. Como una clave utilizada para enlaces de restablecimiento de contraseña

Por supuesto, no habría muchas otras ocasiones en las que podría considerar el uso de dicha construcción.

En primer lugar, se debe utilizar siempre algún tipo de sal que se oculta y que sólo usted sabe. Tenga en cuenta que esta sal debe ser diferente para cada usuario. La sal podría por ejemplo ser calculado como sha256(something random). Esta sal debe entonces ser almacenado en la base de datos junto con el nombre de usuario y contraseña (hash con la sal).

lo que haría al enviar el enlace de restablecimiento de contraseña es crear otra sal (no dar al usuario acceso a nada hash con su sal. Él sabe que su contraseña, por lo que el uso de fuerza bruta que potencialmente podría averiguar su sal). La otra sal, lo que en esencia es solamente un hash de una cadena aleatoria (Es posible que desee ir a por MD5 aquí, como usted ha mencionado que la longitud es un problema), en caso de que guarde en su base de datos.

A menudo sólo puede salirse con la adición de una columna adicional a la tabla de usuarios. Esto, sin embargo, también tiene algunos problemas, principalmente, que una vez que la contraseña se ha restablecido o el usuario se ha activado, se le retire la llave de la base de datos, lo que resulta en la mayoría de las filas que tienen valores nulos, que a su vez trae algunos otros problemas .

Lo que esto esencialmente se reduce a:

  • Hash sus usuarios contraseñas utilizando una sal única-para-el-usuario ( y quizá una sal mundial, secreta).
  • generar una clave hash por una serie de fuentes aleatorias o pseudoaleatorias como marcas de tiempo, o incluso mt_rand() random.org si realmente quiere cosas al azar.
  • Nunca use su sal global o la sal que es única para el usuario de hash cualquier cosa que el usuario tiene acceso a, incluyendo teclas de restablecimiento de contraseñas, claves de activación, etc.

Por favor, no es que yo soy de ninguna manera un experto en seguridad, y probablemente me he olvidado de una serie de cosas, y yo lo he dicho algunas cosas muy malas prácticas. Sólo mis 5 centavos; -)

Otros consejos

¿Por qué utilizar cualquiera de los datos del usuario como base para la clave de autorización?

supongo que usted está almacenando los datos de activadas en una base de datos ¿por qué no sólo tiene que añadir un registro adicional que es simplemente una clave aleatoria (tal vez una md5'ed uniqid con una cierta manipulación adicional) y después comprobar contra de eso?

Fue lo suficientemente seguro justo hasta el punto en el que publicó su método en el Internet! Esto se debe a que confiaban en la seguridad por oscuridad, que no es una buena idea.

Usted debe utilizar algún tipo de función resumen con clave o MAC idealmente, que incorpora una clave secreta conocida sólo por usted.

Por qué no hacer campo de código de índice único? Por lo tanto no habrá nunca collsisions?

Además, si no es necesario para crear hash a partir de la entrada del usuario y hacerla coincidir con hash de base de datos (correo electrónico de confirmación, restablecer la contraseña, etc.) - se puede agregar una cadena aleatoria al cuerpo de hash, como md5('xxx'.$username.'xxx'.time().'xxx'.rand())

¿Por qué no pedir al usuario que introduzca su nombre de usuario y su código, eliminando así cualquier problema con la colisión? No se pierde nada con la seguridad sabia ya que todavía está pidiendo la llave que les gustaría conseguir desde el correo electrónico, sino que dejaras de ellos es capaz de restablecer las contraseñas de otros usuarios.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top