2009-02-10 7 views
10

Quiero unserialize una cadena session_encode() 'd de datos de sesión a mi propia serie (es decir, no a $_SESSION.)¿Cómo puedo deserializar datos de sesión en una variable arbitraria en PHP?

No parece ser una función incorporada que se encarga de esto. Hay session_decode() pero escribe directamente en el $_SESSION superglobal. Hay unserialize() pero devuelve falso en session_encode() 'd strings ya que tienen un formato ligeramente diferente.

¿Cuál es la mejor manera de hacerlo?

EDIT: Este es el código Fui con: http://us.php.net/manual/en/function.session-decode.php#79244

Respuesta

7

ver los comentarios en la página del manual de PHP session_decode. Tiene un montón de funciones de usuario para manejar la decodificación de una cadena session_encode manualmente. Hasta donde yo sé, esa es la única forma de hacerlo.

+0

Utilicé la primera respuesta en esa página de manual. He editado mi publicación para incluir un enlace directo a esa respuesta. –

+0

Noté que las soluciones publicadas php.net tienen un defecto grave. He contribuido con mi propia solución que evita el uso de una expresión regular. También lo publicaré aquí. – Halcyon

-7

¿Por qué no haces algo como esto?

$myVariable = serialize($_SESSION); 
$sessionCopy = unserialize($myVariable); 

¡Buena suerte!

+4

Porque las sesiones se serializan en un formato diferente para serializar/deserializar() –

+0

Bueno, sí, pero puede establecer session.serialize_handler en php_serialize. Ver http://php.net/manual/session.configuration.php#ini.session.serialize-handler para más detalles – Greg

17

Noté que las soluciones publicadas (en php.net) para decodificar manualmente las sesiones no son perfectas, así que contribuí con una solución más robusta.

La solución preg_match nunca puede funcionar. No es tan difícil encontrar un caso que pueda romper la deserialización. En el caso de Jason-joeymail es roturas en:

$_SESSION["test"] = ";oops|"; 

A continuación puede encontrar mi solución. No utiliza una expresión regular, sino la reversibilidad de la operación de serialización y la 'función' que serialize ignora toda entrada adicional cuando cree que está hecha. De ninguna manera es una solución hermosa o particularmente rápida, pero es una solución más robusta. He agregado un deserializador para "php" y "php_binary". Debería ser trivial agregar uno para "wddx".

class Session { 
    public static function unserialize($session_data) { 
     $method = ini_get("session.serialize_handler"); 
     switch ($method) { 
      case "php": 
       return self::unserialize_php($session_data); 
       break; 
      case "php_binary": 
       return self::unserialize_phpbinary($session_data); 
       break; 
      default: 
       throw new Exception("Unsupported session.serialize_handler: " . $method . ". Supported: php, php_binary"); 
     } 
    } 

    private static function unserialize_php($session_data) { 
     $return_data = array(); 
     $offset = 0; 
     while ($offset < strlen($session_data)) { 
      if (!strstr(substr($session_data, $offset), "|")) { 
       throw new Exception("invalid data, remaining: " . substr($session_data, $offset)); 
      } 
      $pos = strpos($session_data, "|", $offset); 
      $num = $pos - $offset; 
      $varname = substr($session_data, $offset, $num); 
      $offset += $num + 1; 
      $data = unserialize(substr($session_data, $offset)); 
      $return_data[$varname] = $data; 
      $offset += strlen(serialize($data)); 
     } 
     return $return_data; 
    } 

    private static function unserialize_phpbinary($session_data) { 
     $return_data = array(); 
     $offset = 0; 
     while ($offset < strlen($session_data)) { 
      $num = ord($session_data[$offset]); 
      $offset += 1; 
      $varname = substr($session_data, $offset, $num); 
      $offset += $num; 
      $data = unserialize(substr($session_data, $offset)); 
      $return_data[$varname] = $data; 
      $offset += strlen(serialize($data)); 
     } 
     return $return_data; 
    } 
} 

Uso:

Session::unserialize(session_encode()); 
+0

El código +1 es un poco feo, pero este es el que funcionó para mí, otras soluciones no. – Mahn

+0

Esto es útil para cualquier persona que quiera analizar datos de sesión desde la línea de comandos, porque 'session_decode' solo funciona si tiene una sesión abierta. –

+1

¿Algún punto de referencia comparado con el siguiente? '$ cur = session_encode(); session_decode ($ codded_data);/* datos codificados puestos en $ _SESSION */session_decode ($ cur);/* current $ _SESSION restored */' –

1

La costumbre 'php' deserialise función anterior se puede hacer más limpia, evitando el enfoque de 'incrementar compensar' a favor de comer poco a poco la cadena de sesión de entrada.

yo no he comprobado cómo se compara en términos de velocidad, pero es sin duda más ordenado (y ahorra llamadas a STRLEN en el bucle while repite)

$r = array(); 
while ($i = strpos($str, '|')) 
{ 
    $k = substr($str, 0, $i); 
    $v = unserialize(substr($str, 1 + $i)); 
    $str = substr($str, 1 + $i + strlen(serialize($v))); 
    $r[$k] = $v; 
} 
return $r; // session data are now in a normal array 
+0

@Michael Szyndel: mi respuesta se refería específicamente al manejador 'php' de arriba porque ese era un valor específico en una declaración de" caso ". Al editar innecesariamente mi publicación para comenzar," PHP deserializó ... "Este detalle se ha perdido. – itl

0

Esto funcionó para mí:

/* storre current session */ 
$current_session = session_encode(); 

/* extract $other_user_session from file or database, 
    into the $_SESSION global variable */ 
session_decode($other_user_session); 

/* use the other user session data: $something = $_SESSION['something']; */ 

/* restore previous sesison info */ 
session_decode($current_session); /* current $_SESSION restored */ 
0
function data_session_decode($data){ 
    $data = array_filter(explode(';',$data)); 
    $list_data = array(); 
    foreach($data as $key => $dat){ 
     if(!empty($dat)){ 
      $data[$key] = array_filter(explode('|',$dat)); 
      if(substr($data[$key][1], 0, 1) == 'i'){ 
       $list_data[$data[$key][0]] = strstr($data[$key][1], ':'); 
       $list_data[$data[$key][0]] = substr($list_data[$data[$key][0]], 1); 
      }elseif(substr($data[$key][1], 0, 1) == 's'){ 
       $list_data[$data[$key][0]] = strstr($data[$key][1], '"'); 
       $list_data[$data[$key][0]] = substr($list_data[$data[$key][0]], 0, -1); 
       $list_data[$data[$key][0]] = substr($list_data[$data[$key][0]], 1); 
      }else{ 
       unset($data[$key]); 
      } 
     } 
    } 
    unset($data); 
    return $list_data; 
} 

// AQUÍ datos de la sesión EX:

$ DATASESSION = 'nombre_usuario | s: 8: "Usted Nombre"; fecha | i: 1459396063';

// Sale

print_r ($ this-> data_session_decode ($ DATASESSION));

Cuestiones relacionadas