2009-02-10 18 views
10

Voglio unserialize una stringa session_encode() 'd dei dati di sessione al mio array (vale a dire di non $_SESSION.)Come posso annullare la serializzazione dei dati di sessione su una variabile arbitraria in PHP?

Non sembra essere una funzione in-built che gestisce questo. C'è session_decode() ma scrive direttamente sul super-global $_SESSION. C'è unserialize() ma restituisce false sulle stringhe session_encode() in quanto sono un formato leggermente diverso.

Qual è il modo migliore per farlo?

EDIT: Questo è il codice sono andato con: http://us.php.net/manual/en/function.session-decode.php#79244

risposta

7

Scopri i commenti nella pagina del manuale di PHP session_decode. Ha un sacco di funzioni utente per gestire la decodifica di una stringa session_encode manualmente. Per quanto ne so, questo è l'unico modo per andare.

+0

Ho usato la prima risposta su quella pagina di manuale. Ho modificato il mio post per includere un collegamento diretto a quella risposta. –

+0

Ho notato che le soluzioni pubblicate su php.net hanno un grave difetto. Ho contribuito con la mia soluzione che evita l'uso di un'espressione regolare. Lo posterò anche qui. – Halcyon

-7

Perché non fai qualcosa di simile?

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

Buona fortuna!

+4

Poiché le sessioni sono serializzate in un formato diverso per serializzare/unserialize() –

+0

Bene, sì, ma è possibile impostare session.serialize_handler su php_serialize. Vedere http://php.net/manual/session.configuration.php#ini.session.serialize-handler per dettagli – Greg

17

Ho notato che le soluzioni pubblicate (su php.net) per le sessioni di decodifica manuale non sono perfette, quindi ho contribuito a una soluzione più solida.

La soluzione preg_match non può mai funzionare. Non è così difficile trovare un caso che potrebbe rompere la serializzazione. Nel caso di jason-joeymail è break su:

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

Qui di seguito potete trovare la mia soluzione. Non usa un'espressione regolare, ma piuttosto la reversibilità dell'operazione di serializzazione e la 'caratteristica' che serializza ignora tutti gli ulteriori input quando pensa di averlo fatto. Non è affatto una soluzione bella o particolarmente veloce, ma è una soluzione più robusta. Ho aggiunto un deserializzatore per "php" e "php_binary". Dovrebbe essere banale aggiungerne uno per "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; 
    } 
} 

Usage:

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

codice +1 è un po 'brutto, ma questo è quello che ha funzionato per me, altri workaround no. – Mahn

+0

Questo è utile per chiunque voglia analizzare i dati della sessione dalla riga di comando, perché 'session_decode' funziona solo se si ha una sessione aperta. –

+1

Qualsiasi benchmark rispetto al seguente? '$ cur = session_encode(); session_decode ($ encoded_data);/* dati codificati inseriti in $ _SESSION */session_decode ($ cur);/* corrente $ _SESSION ripristinata */' –

1

L'usanza 'php' deserialise funzione di cui sopra può essere fatta più pulita, evitando l'approccio 'incremento di offset' a favore di mangiare a poco a poco la stringa di input della sessione.

non ho controllato come si paragona in termini di velocità, ma è certamente più ordinato (e consente di evitare le chiamate al strlen nel ciclo while)

$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: la mia risposta si riferiva specificamente al gestore 'php' sopra perché era un valore specifico in una dichiarazione" caso ". Modificando inutilmente il mio post per iniziare" deserializzazione di PHP .. "questo dettaglio è stato perso. – itl

0

Questo ha funzionato per me:

/* 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; 
} 

// QUI dati della sessione EX:

$ DataSession = 'user_name | s: 8: "È il nome"; data | i: 1.459.396,063 mila';

// Out

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