start sesiones pasar paginas manejo guardar entre ejemplos ejemplo datos control php authentication cookies remember-me

sesiones - Sistema de inicio de sesión de PHP: Recordarme(cookie persistente)



pasar variables de session entre paginas php (2)

Esta pregunta ya tiene una respuesta aquí:

Me gustaría agregar una opción de casilla de verificación "recordarme" antes de iniciar sesión.

¿Cuál es la mejor forma de almacenar de forma segura una cookie en el navegador del usuario?

Por ejemplo, Facebook tiene su casilla de "recordarme" para que cada vez que ingrese a Facebook.com ya esté conectado.

Mi inicio de sesión actual usa sesiones simples.


Actualización (13/08/2017) : para entender por qué estamos separando selector y token , en lugar de simplemente usar un token , lea este artículo sobre cómo dividir tokens para evitar ataques de tiempo en consultas SELECT.

Voy a extraer la estrategia descrita en esta publicación de blog sobre la autenticación segura a largo plazo, ya que abarca mucho terreno y solo nos interesa la parte "recordarme" .

Preámbulo - Estructura de la base de datos

Queremos una tabla separada de la tabla de nuestros usuarios que se vea así (MySQL):

CREATE TABLE `auth_tokens` ( `id` integer(11) not null UNSIGNED AUTO_INCREMENT, `selector` char(12), `token` char(64), `userid` integer(11) not null UNSIGNED, `expires` datetime, PRIMARY KEY (`id`) );

Lo importante aquí es que el selector y el token son campos separados.

Después de iniciar sesión

Si no tiene random_bytes() , simplemente tome una copia de random_compat .

if ($login->success && $login->rememberMe) { // However you implement it $selector = base64_encode(random_bytes(9)); $authenticator = random_bytes(33); setcookie( ''remember'', $selector.'':''.base64_encode($authenticator), time() + 864000, ''/'', ''yourdomain.com'', true, // TLS-only true // http-only ); $database->exec( "INSERT INTO auth_tokens (selector, token, userid, expires) VALUES (?, ?, ?, ?)", [ $selector, hash(''sha256'', $authenticator), $login->userId, date(''Y-m-d/TH:i:s'', time() + 864000) ] ); }

Re-autenticando en la carga de la página

if (empty($_SESSION[''userid'']) && !empty($_COOKIE[''remember''])) { list($selector, $authenticator) = explode('':'', $_COOKIE[''remember'']); $row = $database->selectRow( "SELECT * FROM auth_tokens WHERE selector = ?", [ $selector ] ); if (hash_equals($row[''token''], hash(''sha256'', base64_decode($authenticator)))) { $_SESSION[''userid''] = $row[''userid'']; // Then regenerate login token as above } }

Detalles

Usamos 9 bytes de datos aleatorios (base64 codificados para 12 caracteres) para nuestro selector. Esto proporciona 72 bits de espacio de teclado y, por lo tanto, 2 36 bits de resistencia a la colisión (ataques de cumpleaños), que es mayor que nuestra capacidad de almacenamiento ( integer(11) UNSIGNED ) por un factor de 16.

Usamos 33 bytes (264 bits) de aleatoriedad para nuestro autenticador real. Esto debería ser impredecible en todos los escenarios prácticos.

Almacenamos un hash SHA256 del autenticador en la base de datos. Esto mitiga el riesgo de suplantación de usuario después de filtraciones de información.

Volvemos a calcular el hash SHA256 del valor del autenticador almacenado en la cookie del usuario y luego lo comparamos con el hash SHA256 almacenado utilizando hash_equals() para evitar ataques de temporización.

Separamos el selector del autenticador porque las búsquedas DB no son de tiempo constante. Esto elimina el impacto potencial de las filtraciones de tiempo en las búsquedas sin causar un golpe de rendimiento drástico.