laravel 兼容原生 PHP session

WBOY
Freigeben: 2016-06-20 12:34:35
Original
2011 Leute haben es durchsucht

版权

  • 作者:陈柳锦
  • 主页: http://www.chenliujin.com
  • 邮箱:liujin.chen@qq.com

背景

使用 laravel 框架对 zencart 站点或其它框架实现的项目(如:ThinkPHP)进行重构,把业务一步一步转移到 laravel 的项目中,此时需要共享两边的 session。需要实现 laravel 生成的 session 数据 PHP 原生 session 可以读取,反之亦然,最终大大降低系统重构的复杂度。

方案

使用相同的序列化算法,保持两边序列化后的结果一致。

laravel session 序列化方法

serialize / unserialize

session.serialize_handler

session.serialize_handler 定义用来序列化/解序列化的处理器名字。 当前支持 PHP 序列化格式 (名为 php_serialize)、 PHP PHP 内部格式 (名为 php 及 php_binary) 和 WDDX (名为 wddx)。 如果 PHP 编译时加入了 WDDX 支持,则只能用 WDDX。 自 PHP 5.5.4 起可以使用 php_serialize。 php_serialize 在内部简单地直接使用 serialize/unserialize 函数,并且不会有 php 和 php_binary 所具有的限制。 使用较旧的序列化处理器导致 $_SESSION 的索引既不能是数字也不能包含特殊字符(| and !) 。 使用 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 # 使用新的序列化方法
    Nach dem Login kopieren

laravel

session.name :config/session.php

    'cookie' => 'zenid', # 与 zencart 保持一致
Nach dem Login kopieren

redis key prefix:config/cache.php

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

laravel session 存储:Illuminate\Session\Store.php

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

laravel session 读取:Illuminate\Session\Store.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 [];    }
Nach dem Login kopieren

验证对方保存的 session 数据可以正常读取

zencart 写,laravel 读

  • zencart 写

    PHPREDIS_SESSION:02103fd8mo5jb7qia51lnu7lh5

    "a:1:{s:13:\"securityToken\";s:32:\"3c83dcba20e98cfd77ba70db6de93497\";}"
    Nach dem Login kopieren

  • laravel 读

    读取失败

  • debug

    <?  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 [];  }
    Nach dem Login kopieren
  • error_log

    [15-Mar-2016 07:59:01 UTC] array ('securityToken' => '03eac95413cbfcc16ea599f36d2e24e2',)
    Nach dem Login kopieren
  • 问题原因

    $data = $this->handler->read($this->getId()),$data 是一个数组,印证了可以反序列化成功,但是是被 handler->read 多反序列化了一次(取出来应该是一个字符串,后面才进行反序列化),说明 handler->read 具有反序列化功能。因此 zencart 保存和读取时需要进行多一次序列化和反序列化。

zencart 多进行一次序列化和反序列化

  • <?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;}
    Nach dem Login kopieren
  • <?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;}
    Nach dem Login kopieren
  • redis
    "s:67:\"a:1:{s:13:\"securityToken\";s:32:\"8a190ebc150a39dd8a7bd46a9c2665cc\";}\";"
    Nach dem Login kopieren
  • 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;}
    Nach dem Login kopieren
  • redis
    • key PHPREDIS_SESSION:6d8d36a7abe4318891c60308f47bb8ed489bfb5a
    • value
      "s:67:\"a:1:{s:13:\"securityToken\";s:32:\"03eac95413cbfcc16ea599f36d2e24e2\";}\";"
      Nach dem Login kopieren
    • 此时 laravel 和 zencart 写入 redis 的数据保持了一致
  • zencart 读

session key 冲突

两边都在 session 中保存 language,此时需保持 key 和 value 定义一致,否则会将对方的数据覆盖掉,引起异常。

  • zencart
    $_SESSION['language'] = 'english';
    Nach dem Login kopieren
  • laravel
    Session::put('language', 'en');
    Nach dem Login kopieren
Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!