用JavaScript解析PHP Session

10

最近,我开始使用Node.js扩展我的网站,并意识到需要一个会话处理程序来处理PHP会话。现在一切都很顺利,Node.js可以读取PHP会话并将其自己的会话与PHP会话一起传播。我正在使用数据库会话,因此会话数据存储在数据库字段中。

但是,我遇到了一个小问题。我试图将会话数据读入Node.js,但它是一个非常奇怪的字符串。我已经能够将每个会话变量的结构确定为:

'field_name'|'type':'length':'value';

对于某些字符串,值字段可能会缺失,对于其他字符串,长度可能会缺失(当变量为 Null 时)。类型也可以不止是 b、s、i;它也可以是 N(NULL)。

我最初考虑过为 JS 制作一个庞大的翻译器,但这似乎是一种非常错误的做法。

这里有人尝试过在 JS 中提取 PHP 会话变量吗?是否有任何脚本可以帮助?也许有一些在 PHP 端可以使用的格式化工具可以使我的生活在 node.js 中更轻松?

编辑:模式如下:

{ _id: { id: 'L:\u00c1\u009d\u008e\u00ad\u000e}<\u0002\u0000\u0000' }
, session_id: 'a2clfnjhopv1srs5k5elgbfjv5'
, user_id: 0
, session_data:     'logged|b:0;uid|i:0;server_key|N;AUTH_TIER2|b:0;email|s:0:"";cheese|s:6:"cheese";'
, active: 1
, expires: 1278920567
}

这是MongoDB用户会话的记录。需要翻译的字段是session_data。当我尝试将其格式化为代码时,由于某些原因,stackoverflow无法对其进行格式化,出现了某种格式错误。

我之前尝试过将该字段转换为JSON,但失去了其类型并未能读取Null条目,因此我停止了该操作。

谢谢。


1
我以前没有使用过node.js。在将未序列化的PHP会话数据传递给node.js之前,是否可以使用json_encode对其进行编码? - Gordon
你能展示一个例子而不是模式吗?当某些东西缺失时它会是什么样子? - gblazex
我添加了模式,但是当我粘贴它时出现了某种错误,而stackoverflow无法将数据格式化为代码:(。正如我在编辑中所述,我尝试过JSON,但似乎会破坏字符串,使得无法检索会话数据:(。也许这其中有什么问题,如果我创建一个节点字段并将会话数据复制到json字符串中...并为该字段创建一个dejsonifier....嗯,可能会起作用。 - Sammaye
修复了代码。为了以后的参考,您需要在缩进的代码和非缩进的文本之间至少留一个空行,以便正确格式化。 - Yacoby
4个回答

5

我相信PHP使用serialize和unserialize函数来处理会话数据。

在PHP.JS中有一个unserialize的JavaScript实现,你可以在这里找到:http://phpjs.org/functions/unserialize


@Jani 我不确定这是否可以使用 serialize/unserialize 处理,而应该使用 session_encode/session_decode。 - Gordon
你可能是对的Gordon。看起来还没有JS实现 - @Sammaye,你最好的选择可能是尝试使用unserialize使其运行,因为格式非常相似但不完全是1比1的,并且如果你遇到问题,请修改该函数以更像session_decode(比从头开始编码少了更多的工作)。 - Jani Hartikainen
是的,看起来如果你像这样添加'fieldname'|'serialisedarray',它可以与JS完美匹配。在我确认它能够正常工作之前,需要进行更多的测试。我需要将对象存储在数组中,以便Node.js可以忽略它们但不会删除它们,但似乎它可以正常工作:D - Sammaye
我刚刚注意到我可以在node.js中使用php...如果它直接与php通信,我可能能够运行快速的反序列化函数。 - Sammaye
是的,这个完美地运作了。我能够创建一个node.js php会话处理程序,它像野兽一样工作,谢谢 :) - Sammaye
显示剩余2条评论

5

3

以下是我找到的解决方法:强制PHP使用JSON:

使用下面的类,通过session_set_save_handler将数据存储为JSON,并让PHP继续使用自己的系统。 在每个使用session的脚本开头使用此函数来链接此类: http://php.net/manual/ru/function.session-set-save-handler.php

PS:这里的类使用memcache来存储JSON结果对象,在Node.JS中,使用一个memcache对象,并像这样检索:

  • 从cookies中获取PHPSESSID
  • 使用该字符字符串从memcached中获取“sessions/id”的键,其中id是键,session只是字符串(请参见下面的类)。

现在,您应该只在memcache中有JSON,因此使用Node.JS变得更加简单。

PS:当然,您可以使用/改进此功能,也可以将其用于不仅仅是memcache(例如数据库)。

<?php
/**
 * This class is used to store session data with memcache, it store in json the session to be used more easily in Node.JS
 */
class memcacheSessionHandler{
    private static $lifetime = 0;
    private static $memcache = null;

    public function __construct(){
            self::$memcache = new Memcache();
            self::$memcache->addServer('localhost', 11211);
}

    public function __destruct(){
            session_write_close();
            self::$memcache->close();
            self::$memcache = null;
    }

    public static function open(){
            self::$lifetime = ini_get('session.gc_maxlifetime');
            return true;
    }

    public static function read($id){
            $tmp = $_SESSION;
            $_SESSION = json_decode(self::$memcache->get("sessions/{$id}"), true);
            $new_data = session_encode();
            $_SESSION = $tmp;
            return $new_data;
    }

    public static function write($id, $data){
            $tmp = $_SESSION;
            session_decode($data);
            $new_data = $_SESSION;
            $_SESSION = $tmp;
            return self::$memcache->set("sessions/{$id}", json_encode($new_data), 0, self::$lifetime);
    }

    public static function destroy($id){
            return self::$memcache->delete("sessions/{$id}");
    }

    public static function gc(){
            return true;
    }

    public static function close(){
            return true;
    }
}
?>

2

我遇到了同样的问题。我需要将phpnode.js集成。我使用js-php-unserialize来完成这个任务。使用起来非常简单。

var PHPUnserialize = require('php-unserialize');
console.log(PHPUnserialize.unserializeSession(yourData));

For example if you

var yourData = 'A|s:1:"B";userID|s:24:"53d620475e746b37648b4567";';

您将会得到以下结果:
{
  A: 'B',
  userID: '53d620475e746b37648b4567'
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接