2010-01-09 12 views
15

Soy un principiante que trabaja en un script de inicio de sesión en PHP. Esta es la declaración token de forma que tengo hasta ahora:Uso y manejo de tokens de formulario PHP

$_SESSION["form_token"] = md5(rand(time(), true)) ; 

se emite la declaración que acaba cuando el usuario indica que él/ella quiere iniciar sesión.

Mi comprensión limitada es que el objetivo de tokens es identificar a un usuario único en un punto único en el tiempo y disfrazar la información del token de formulario.

Entonces todo se vuelve borroso. Aquí están mis 3 preguntas abiertas:

  1. ¿Cuándo es el mejor momento para "verificar" el token del formulario por razones de seguridad?

  2. ¿Cómo puedo verificarlo?

  3. ¿Cuándo, si alguna vez, "destruyo" el token de formulario? (OIA, sería el token forma mantenerse "activo" hasta que el usuario cierra la sesión?

+2

FYI MD5 es algo limitado y si se necesita generar una cadena aleatoria le sugiero que utilice esto en su lugar: $ id = sha1 (mt_rand()); Si usas rand() solo obtienes 32,000 combinaciones posibles. – TravisO

+0

relacionado: http://stackoverflow.com/questions/5111007/does-php-have-an-authenticity-token-like-rails – baptx

Respuesta

12

No hay necesidad de hacer lo que intenta realizar. Cuando inicia una sesión en PHP con session_start(), ya se generó un SESSIONID único para usted. Debe no poner esto en el formulario. Se maneja mediante cookies por defecto. Tampoco es necesario verificar el SESSIONID, que nuevamente se maneja para usted.

Usted es responsable de autenticar al usuario y almacenar su identidad autenticada (por ejemplo, $ _SESSION [ 'user_id'] = $ ID de usuario en la sesión. Si un usuario cierra la sesión se destruye su sesión con session_destroy.

Usted debe asegúrese de que session_start() sea uno de los primeros elementos para todas las páginas de su sitio.

Aquí es un ejemplo básico:

<?php 
session_start(); // starts new or resumes existing session 
session_regenerate_id(true); // regenerates SESSIONID to prevent hijacking 

function login($username, $password) 
{ 
    $user = new User(); 
    if ($user->login($username, $password)) { 
     $_SESSION['user_id'] = $user->getId(); 
     return true; 
    } 
    return false; 
} 

function logout() 
{ 
    session_destroy(); 
} 

function isLoggedIn() 
{ 
    return isset($_SESSION['user_id']); 
} 

function generateFormHash($salt) 
{ 
    $hash = md5(mt_rand(1,1000000) . $salt); 
    $_SESSION['csrf_hash'] = $hash 
    return $hash; 
} 

function isValidFormHash($hash) 
{ 
    return $_SESSION['csrf_hash'] === $hash; 
} 

Editar: no he entendido bien la pregunta original. Agregué los métodos relevantes arriba para generar y validar hashes de formulario;

Por favor, consulte los siguientes recursos:

+0

Hay algo que no entiendo. También uso las sesiones de php para tokens, pero cada vez que modifico una sesión, todas se modifican (la "fecha de modificación" de todos los cambios de archivos tmp). ¿Hay alguna conexión entre las sesiones que identifican diferentes usuarios? – Sthe

18

esto es para evitar CSRF ataca

http://en.wikipedia.org/wiki/Cross-site_request_forgery

un sitio malicioso podría mostrar teóricamente una forma que los puestos a su aplicación, el formulario puede contener instrucciones que causan una violación de datos o alguna acción no deseada. El usuario podría ser engañado al enviar el formulario que la aplicación aceptaría porque el usuario ya inició sesión. Un token de formulario asegura que el formulario fue creado por su sitio y no otro sitio.

comprobar que HTTP_REFERER a menudo es lo suficientemente bueno, pero no una solución tan completa (https, por ejemplo, no enviará la cadena de referencia).

si realmente desea proteger todos los formularios con un token, puede crear algunas funciones de conveniencia como emitToken() y checkToken() que lo harán funcionar en todo el sitio.

algunos ejemplos:

http://phpsec.org/projects/guide/2.html

http://www.rodsdot.com/php/CSRF_Form_Protection.php

+2

HTTP_REFERER no es confiable, ¡nunca confíe en él porque puede editarse fácilmente! – Heitor