8

ある意味で、この質問はこの質問の延長として見ることができます

大規模な本番Webサイトのテーブルに格納されているセッションデータの逆シリアル化とシリアル化を処理するクラスをリリースして、任意のセッションデータを編集できるようにすることを検討しています。

問題は、デコードされた配列を返さずにsession_decode()現在の配列を設定し、特定の配列をエンコードしないことです(現在のセッションのシリアル化された文字列のみを返します)。$_SESSIONsession_encode()

デフォルトのPHPセッションシリアル化ハンドラーは単にserialize()セッションのエンコードに使用するわけではないため、セッションのエンコードとデコードの同じ機能を取得する唯一の方法は、グローバル$_SESSION変数を移動することです(つまり、セッションに保存し、データを取得して復元します)。 )または、実行する内容の実装を再現しようとすることによってsession.serialize_handler

あまり邪魔にならないように見えるので、後者の複製アプローチを選択しました。ドキュメントのsession_encodesession_decodeのコメントセクションで、この複製が何度も試みられています。最も信頼できると思われるものを2つ選び、それらを適用しました。デコード方法は非常に堅牢に見えますが、エンコード方法は機能しますが、5年以上前に投稿されました

これらのメソッドが機能しなくなる原因となる目に見えないエッジケースがある可能性があるという理由だけで、まだ展開することには消極的です。

最終的に、私は探しています:

  • 以下の方法を破る例、または
  • これらの方法が本番環境で使用されており、壊れないという安心感
  • おそらく、本番環境で試され、テストされた代替案ですか?

よろしくお願いします!

コード:

class Session extends BaseSession
{
    /**
     * Taken from http://www.php.net/manual/en/function.session-decode.php#108037
     */
    public function unserialized() {
        $session_data = $this->content;
        $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");
        }
    }

    /**
     * Taken from http://www.php.net/manual/en/function.session-encode.php#76425
     */
    public function serialize($array, $safe = true) {
        // the session is passed as refernece, even if you dont want it to
        if( $safe ) $array = unserialize(serialize( $array )) ;
        $raw = '' ;
        $line = 0 ;
        $keys = array_keys( $array ) ;
        foreach( $keys as $key ) {
            $value = $array[ $key ] ;
            $line ++ ;
            $raw .= $key .'|' ;
            if( is_array( $value ) && isset( $value['huge_recursion_blocker_we_hope'] )) {
                $raw .= 'R:'. $value['huge_recursion_blocker_we_hope'] . ';' ;
            } else {
                $raw .= serialize( $value ) ;
            }
            $array[$key] = Array( 'huge_recursion_blocker_we_hope' => $line ) ;
        }

        $this->content = $raw;
        $this->save();
    }


    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;
    }
}
4

1 に答える 1

1

Igbinary ( https://github.com/igbinary/igbinary/ ) は、標準の php シリアライザーの代替品です。時間とスペースを消費するテキスト表現の代わりに、igbinary は PHP データ構造をコンパクトなバイナリ形式で保存します。シリアル化されたデータに memcached または同様のメモリ ベースのストレージを使用すると、大幅に節約できます。ストレージ要件の約 50% の削減が期待できます。特定の数は、データによって異なります。

非シリアライゼーションのパフォーマンスは、少なくとも標準の PHP シリアライザーと同等です。シリアル化のパフォーマンスは、重複文字列の追跡を有効にする「compact_strings」オプションに依存します。文字列がハッシュ テーブルに挿入され、オーバーヘッドが追加されます。通常のシナリオでは、使用パターンは「めったにシリアライズせず、頻繁にアンシリアライズする」ため、これはあまり重要ではありません。"compact_strings" オプションを使用すると、igbinary は通常、標準のシリアライザーよりも少し遅くなります。それがなければ、少し速くなります。

特徴

  • 標準の PHP シリアライザーと同じデータ型 (null、bool、int、float、string、array、objects) をサポートします。
  • __autoload&unserialize_callback_func
  • __sleep&__wakeup
  • シリアライズ可能なインターフェース
  • プラットフォーム間のデータ移植性 (32/64 ビット、エンディアン)
  • Linux amd64、Linux ARM、Mac OSX x86、HP-UX PA-RISC、および NetBSD sparc64 でテスト済み
  • シリアライゼーション ハンドラーとして APC オペコード キャッシュに接続 (APC 3.1.7+)
  • PHP 5.2 および 5.3 と互換性があります

それが役に立てば幸い

于 2013-03-24T21:04:40.230 に答える