ホームページ  >  記事  >  バックエンド開発  >  ネイティブPHPセッションと互換性のあるlaravel

ネイティブPHPセッションと互換性のあるlaravel

WBOY
WBOYオリジナル
2016-06-20 12:34:351992ブラウズ

著作権

  • 著者: Chen Liujin
  • ホームページ: http://www.chenliujin.com
  • メール: liujin. chen @qq.com

背景

laravel フレームワークを使用して、zencart サイトまたは他のフレームワーク (ThinkPHP など) によって実装されたプロジェクトを再構築し、ビジネスを laravel プロジェクトに移行するステップステップ により、この時点で両側のセッションを共有する必要があります。 laravel によって生成されたセッション データは PHP ネイティブ セッションによって読み込むことができ、その逆も可能であることを認識する必要があります。これにより、最終的にシステム再構築の複雑さが大幅に軽減されます。

解決策

同じシリアル化アルゴリズムを使用して、シリアル化された結果の両側で一貫性を保ちます。

Laravel セッションシリアル化メソッド

serialize / unserialize

session.serialize_handler

session.serialize_handler はシリアル化/逆シリアル化に使用されるプロセッサ名を定義します。 現在サポートされているのは、PHP シリアル化形式 (php_serialize という名前)、PHP PHP 内部形式 (php および php_binary という名前)、および WDDX (wddx という名前) です。 PHP が WDDX サポートを使用してコンパイルされている場合は、WDDX のみを使用できます。 php_serialize は PHP 5.5.4 以降で利用可能です。 php_serialize は内部的には、serialize/unserialize 関数を直接使用するだけであり、php や php_binary のような制限はありません。 古いシリアライザーを使用すると、$_SESSION のインデックスが数値でなくなり、特殊文字 (| と !) が含まれなくなります。 php_serialize を使用して、スクリプトの終了時に数値および特殊文字のインデックスによって引き起こされるエラーを回避します。 デフォルトではphpが使用されます。

处理器 对应的存储格式
php_binary 键名的长度对应的 ASCII 字符+键名+经过 serialize() 函数反序列处理的值
php 键名+竖线+经过 serialize() 函数反序列处理的值
php_serialize (php>=5.5.4) 经过 serialize() 函数反序列处理的数组

php 5.3.3

php 5.5.32

PHP

  • PHP を 5.5 にアップグレードします
  • php.ini
    [Session]session.serialize_handler = php_serialize # 使用新的序列化方法

laravel

session.name: config/session.php

    'cookie' => 'zenid', # 与 zencart 保持一致

redis キープレフィックス: config/cache.php

<?    'stores' => [        'redis' => [            'driver' => 'redis',            'connection' => 'default',            'prefix' => 'PHPREDIS_SESSION', # 与 zencart 保持一致         ],    ],

laravel セッションストレージ: IlluminateSessionStore.php

<?    public function save()    {        $this->addBagDataToSession();         $this->ageFlashData();         $this->handler->write($this->getId(), $this->prepareForStorage(serialize($this->attributes)));         $this->started = false;    }

laravel セッション読み取り: IlluminateSessionStore.php

<?    /**     * Read the session data from the handler.     *     * @return array     */    protected function readFromHandler()    {        $data = $this->handler->read($this->getId());         if ($data) {            $data = @unserialize($this->prepareForUnserialize($data));             if ($data !== false && $data !== null && is_array($data)) {                return $data;            }        }         return [];    }

相手が保存したセッションデータが正常に読み込めることを確認します

zencart writes, laravel reads

  • zencart writes

    PHPREDIS_SESSION :02103fd8mo5jb7qia51lnu7lh5

    "a:1:{s:13:\"securityToken\";s:32:\"3c83dcba20e98cfd77ba70db6de93497\";}"
  • laravel 読み取り

    読み取りに失敗しました

  • デバッグ

    <?  protected function readFromHandler()  {      $data = $this->handler->read($this->getId());       error_log(var_export($data, true)); # 跟踪从 redis 中取出的数据,确定问题原因        if ($data) {          $data = @unserialize($this->prepareForUnserialize($data));           if ($data !== false && $data !== null && is_array($data)) {              return $data;          }      }       return [];  }
  • error_log

    [15-Mar-2016 07:59:01 UTC] array ('securityToken' => '03eac95413cbfcc16ea599f36d2e24e2',)
  • 問題の原因

    $data = $this-> ;handler-> ;read($this->getId())、$data は配列であり、逆シリアル化が成功する可能性があることを証明していますが、handler->read によってもう一度逆シリアル化されました ( string を取り出すと、後でデシリアライズが行われます)、handler->read にデシリアライズ機能があることを示します。したがって、zencart は保存時と読み取り時にもう 1 回シリアル化と逆シリアル化を実行する必要があります。

zencart はもう 1 回シリアル化と逆シリアル化を実行します

  • 書き込み

    <?function _sess_write($key, $val) {  global $SESS_LIFE;   $val = serialize($val); #序列化多一次    $redis_new = new Redis();  $redis_new->pconnect(SESSION_REDIS_HOST_NEW, SESSION_REDIS_PORT_NEW);  $redis_new->auth(SESSION_REDIS_PASSWORD_NEW);  $redis_new->select(SESSION_REDIS_DB_NEW);   $rd_ssk = 'PHPREDIS_SESSION:' . $key ;  $redis_new->setex($rd_ssk,$SESS_LIFE, $val);  return true;}
  • read

    <?function _sess_read($key) {  $redis_new = new Redis();  $redis_new->pconnect(SESSION_REDIS_HOST_NEW, SESSION_REDIS_PORT_NEW);  $redis_new->auth(SESSION_REDIS_PASSWORD_NEW);  $redis_new->select(SESSION_REDIS_DB_NEW);  $rd_ssk = 'PHPREDIS_SESSION:' . $key ;  $sess_value = $redis_new->get($rd_ssk);   $sess_value = unserialize($sess_value); #反序列化    return $sess_value;}
  • redis
    "s:67:\"a:1:{s:13:\"securityToken\";s:32:\"8a190ebc150a39dd8a7bd46a9c2665cc\";}\";"
  • laravel は正常に読み取れました

laravel は書き込み、zencart は読み取ります

  • laravel は

    <?public function save(){  $this->addBagDataToSession();   $this->ageFlashData();   # 模拟 session 赋值     $this->attributes = array(      'securityToken' => '03eac95413cbfcc16ea599f36d2e24e2',  );   $this->handler->write($this->getId(), $this->prepareForStorage(serialize($this->attributes)));   $this->started = false;}
  • redis
    • キー PHPREDIS_SESSION:6d8d36a7abe4318891c60308f47bb8ed489bfb5a
    • "s:67:\"a:1:{s:13:\"securityToken\";s:32:\"03eac95413cbfcc16ea599f36d2e24e2\";}\";"
    • 現時点ではlaravelは一貫していますzencart によって redis に書き込まれたデータを使用して
  • zencart は
セッション キーの競合

で双方が言語をセッションに保存します。今回は、キーと値の定義が一貫している必要があります。一貫していないと、相手のデータが上書きされ、例外が発生します。

    ゼンカート
  • $_SESSION['language'] = 'english';
  • laravel
  • Session::put('language', 'en');
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。