PHP nasıl keyfi bir değişkeni oturum verileri unserialize olabilir?

4 Cevap php

Ben kendi dizisine oturum veri session_encode() 'd dize unserialize istiyorum (yani değil $_SESSION.)

Bu işler bir dahili fonksiyonu var gibi görünmüyor. Orada session_decode() ama $_SESSION süper küresel doğrudan yazar. Orada unserialize() ama onlar biraz daha farklı bir biçim konum olarak session_encode() 'dizeleri d false döndürür.

Bunu yapmanın en iyi yolu nedir?

EDIT: Bu ile gittim kodu: http://us.php.net/manual/en/function.session-decode.php#79244

4 Cevap

Elle PHP manuelin session_decode page. It has a bunch of user functions to handle decoding a session_encode dizesinde yorum atın. Bildiğim kadarıyla, o gitmek için tek yoldur.

Ben elle çözme oturumları için (php.net üzerine) yayınlanmıştır çözümler mükemmel değildir, bu yüzden daha sağlam bir çözüm katkısı fark ettik.

The preg_match solution can never work. It's not so hard to find a case that might break unserialization. In the case of jason-joeymail is breaks on:

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

Below you can find my solution. It doesn't use a regular expression but rather the reversibility of the serialize operation and the 'feature' that serialize ignores all further input when it thinks it's done. It's by no means a beautiful or particularly fast solution but it is a more robust solution. I've added a deserializer for "php" and "php_binary". It should be trivial to add one for "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;
    }
}

Kullanımı:

Session::unserialize(session_encode());

Yukarıda özel 'php' deserialise işlevi yavaş yavaş giriş oturumu dize kadar yeme lehine 'artan offset' yaklaşımını kaçınarak temiz yapılabilir.

Ben bu hız açısından karşılaştırır nasıl kontrol ettik, ama kesinlikle tidier (ve while döngüsünde strlen tekrarlanan çağrıları kaydeder)

$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

Neden böyle bir şey yapmak değil mi?

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

İyi şanslar!