转载自: http://gonzalo123.com/2011/07/25/using-node-js-to-store-php-sessions/
最近一直在研究node-php-session的共享,发现这边文章不错,特留下以备后用。谢谢原创作者。等项目结束了,我把我用symfony2+memcached+nodejs实现的session共享方法,也分享一下。
We use sessions when we want to preserve certain data across subsequent accesses. PHP allows us to use different handlers when we’re using sessions. The default one is filesystem, but we can change it with session.save_handler in the php.ini. session.save_handler defines the name of the handler which is used for storing and retrieving data associated with a session. We also can create our own handler to manage sessions. In this post we’re going to create a custom handler to store sessions in a node.js service. Let’s start:
Imagine we’ve got the following php script:
session_start(); if (!isset($_SESSION["gonzalo"])) $_SESSION["gonzalo"] = 0; $_SESSION["gonzalo"]++; $_SESSION["arr"] = array('key' => uniqid()); var_dump($_SESSION);
A simple usage of sessions with PHP. If we reload the page our counter will be incremented by one. We’re using the default session handler. It works without any problem.
The idea is create a custom handler to use a server with node.js to store the session information instead of filesystem. To create custom handlers we need to use the PHP function: session_set_save_handler and rewrite the callbacks for: open, close, read, write, destroy and gc. PHP’s documentation is great. My proposal is the following one:
Our custom handler:
class NodeSession { const NODE_DEF_HOST = '127.0.0.1'; const NODE_DEF_PORT = 5672; static function start($host = self::NODE_DEF_HOST, $port = self::NODE_DEF_PORT) { $obj = new self($host, $port); session_set_save_handler( array($obj, "open"), array($obj, "close"), array($obj, "read"), array($obj, "write"), array($obj, "destroy"), array($obj, "gc")); session_start(); return $obj; } private function unserializeSession($data) { if( strlen( $data) == 0) { return array(); } // match all the session keys and offsets preg_match_all('/(^|;|\})([a-zA-Z0-9_]+)\|/i', $data, $matchesarray, PREG_OFFSET_CAPTURE); $returnArray = array(); $lastOffset = null; $currentKey = ''; foreach ( $matchesarray[2] as $value ) { $offset = $value[1]; if(!is_null( $lastOffset)) { $valueText = substr($data, $lastOffset, $offset - $lastOffset ); $returnArray[$currentKey] = unserialize($valueText); } $currentKey = $value[0]; $lastOffset = $offset + strlen( $currentKey )+1; } $valueText = substr($data, $lastOffset ); $returnArray[$currentKey] = unserialize($valueText); return $returnArray; } function __construct($host = self::NODE_DEF_HOST, $port = self::NODE_DEF_PORT) { $this->_host = $host; $this->_port = $port; } function open($save_path, $session_name) { return true; } function close() { return true; } public function read($id) { return (string) $this->send(__FUNCTION__, array('id' => $id)); } public function write($id, $data) { try { $this->send(__FUNCTION__, array( 'id' => $id, 'data' => $data, 'time' => time(), 'dataJSON' => json_encode($this->unserializeSession($data)))); return true; } catch (Exception $e) { return false; } } public function destroy($id) { try { $this->send(__FUNCTION__, array('id' => $id)); } catch (Exception $e) { return false; } return true; } function gc($maxlifetime) { try { $this->send(__FUNCTION__, array('maxlifetime' => $maxlifetime, 'time' => time())); } catch (Exception $e) { return false; } return true; } private function send($action, $params) { $params = array('action' => $action) + $params; return file_get_contents("http://{$this->_host}:{$this->_port}?" . http_build_query($params)); } }
Our node.js server:
var http = require('http'), url = require('url'), session = require('nodePhpSessions').SessionHandler; var sessionHandler = new session(); var server = http.createServer(function (req, res) { var parsedUrl = url.parse(req.url, true).query; res.writeHead(200, {'Content-Type': 'text/plain'}); res.end(sessionHandler.run(parsedUrl)); }); server.listen(5672, "127.0.0.1", function() { var address = server.address(); console.log("opened server on %j", address); });
As we can see we need the node.js module nodePhpSessions. You can easily install with:
npm install nodePhpSessions
You can see nodePhpSessions library here.
The library is tested with nodeunit. Without TDD is very hard to test things such as garbage collector.:
var session = require('nodePhpSessions').SessionHandler; var sessionHandler = new session(); var parsedUrl; exports["testReadUndefinedSession"] = function(test){ parsedUrl = { action: 'read', id: 'ts49vmf0p732iafr25mdu8gvg2' }; test.equal(sessionHandler.run(parsedUrl), undefined); test.done(); }; exports["oneSessionShouldReturns1"] = function(test){ parsedUrl = { action: 'write', id: 'ts49vmf0p732iafr25mdu8gvg2', data: 'gonzalo|i:1;arr|a:1:{s:3:"key";s:13:"4e2b1a40d136a";}', time: '1311447616', dataJSON: '{"gonzalo":1,"arr":{"key":"4e2b1a40d136a"}}' }; sessionHandler.run(parsedUrl); parsedUrl = { action: 'readAsArray', id: 'ts49vmf0p732iafr25mdu8gvg2' }; test.equal(sessionHandler.run(parsedUrl).gonzalo, 1); test.done(); }; exports["oneSessionShouldReturns2"] = function(test){ parsedUrl = { action: 'write', id: 'ts49vmf0p732iafr25mdu8gvg2', data: 'gonzalo|i:2;arr|a:1:{s:3:"key";s:13:"4e2b1a40d136a";}', time: '1311447616', dataJSON: '{"gonzalo":2,"arr":{"key":"4e2b1a40d136a"}}' }; sessionHandler.run(parsedUrl); parsedUrl = { action: 'readAsArray', id: 'ts49vmf0p732iafr25mdu8gvg2' }; test.equal(sessionHandler.run(parsedUrl).gonzalo, 2); test.done(); }; exports["destroySession"] = function(test){ parsedUrl = { action: 'destroy', id: 'ts49vmf0p732iafr25mdu8gvg2'}; sessionHandler.run(parsedUrl); parsedUrl = { action: 'readAsArray', id: 'ts49vmf0p732iafr25mdu8gvg2' }; test.equal(sessionHandler.run(parsedUrl), undefined); test.done(); }; exports["garbageColector"] = function(test){ parsedUrl = { action: 'write', id: 'session1', data: 'gonzalo|i:1;arr|a:1:{s:3:"key";s:13:"4e2b1a40d136a";}', time: '1111111200', dataJSON: '{"gonzalo":1,"arr":{"key":"4e2b1a40d136a"}}' }; sessionHandler.run(parsedUrl); parsedUrl = { action: 'write', id: 'session2', data: 'gonzalo|i:1;arr|a:1:{s:3:"key";s:13:"4e2b1a40d136a";}', time: '1111111100', dataJSON: '{"gonzalo":1,"arr":{"key":"4e2b1a40d136a"}}' }; sessionHandler.run(parsedUrl); parsedUrl = { action: 'gc', maxlifetime: '100', time: '1111111210'}; sessionHandler.run(parsedUrl); parsedUrl = { action: 'readAsArray', id: 'session2' }; test.equal(sessionHandler.run(parsedUrl), undefined); parsedUrl = { action: 'readAsArray', id: 'session1' }; test.equal(sessionHandler.run(parsedUrl).gonzalo, 1); test.done(); };
Here you can see the output of the tests:
nodeunit testNodeSessions.js testNodeSessions.js ✔ testReadUndefinedSession ✔ oneSessionShouldReturns1 ✔ oneSessionShouldReturns2 ✔ destroySession ✔ garbageColector OK: 6 assertions (5ms)
Now we change the original PHP script to:
include_once 'NodeSessions.php'; NodeSession::start(); if (!isset($_SESSION["gonzalo"])) $_SESSION["gonzalo"] = 0; $_SESSION["gonzalo"]++; $_SESSION["arr"] = array('key' => uniqid()); var_dump($_SESSION);
We start the node.js server:
node serverSessions.js
Now if we reload our script in the browser we will see the same behaviour, but now our sessions are stored in the node.js server.
array(2) { ["gonzalo"]=> int(16) ["arr"]=> array(1) { ["key"]=> string(13) "4e2a9f6a966f4" } }
This kind of techniques are good when clustering PHP applications.
Full code is available on github (node server, PHP handler, tests and examples) here.
相关推荐
Node.js是一款基于Chrome V8引擎的JavaScript运行环境,它让JavaScript可以在服务器端执行,极大地拓宽了JavaScript的应用领域。而TensorFlow是谷歌开发的一款开源机器学习框架,它允许开发者构建、训练和部署各种...
使用 Express、Redis Pub/Sub + Redis SessionStore + Socket.io + Socket.Sessions 的 Node.js 聊天应用程序,可在 Cloud Foundry 上进行扩展笔记该项目现已更新为使用 Node 4.x(不向后兼容)。此外,它还使用了 ...
Using S3 to store files 239 Working with buckets 239 Working with objects 240 Using AWS with a Node server 243 Getting and setting data with DynamoDB 244 Searching the database 247 Sending mail via ...
1. **Node.js**:Node.js是一个基于Chrome V8引擎的JavaScript运行环境,它允许开发者使用JavaScript编写服务器端程序。通过Node.js,开发者可以利用JavaScript的强大能力构建高性能的网络应用。安装Node.js时,只需...
首先,Node.js是一个开放源代码、跨平台的JavaScript运行环境,它允许开发者在服务器端运行JavaScript代码。Node.js基于Chrome的V8引擎,提供了高效的执行性能。在本项目中,Node.js作为后端的基础,负责处理HTTP...
Node.js-注册-登录-应用程序 这是一个使用Node.js,Express,Mongoose...您需要在系统中安装Node.js,NPM和MongoDB。 正在安装 npm install 跑步 nodemon server.js 代码正在运行 :smiling_face_with_heart-eyes: 谢谢
blog/sessions.js - 会话数据访问助手 blog/users.js - 用户数据访问助手 博客/视图/ - html 模板 家庭作业 运行作业 3.1 npm run hw1 跑作业 3.2 cd blog/ npm install node app.js 跑作业 3.3 cd blog/ npm ...
这是一个用于创建基本 node.js 应用程序框架的生成器。 可选功能: 服务器端修女的意见 客户 nunjucks 意见 i18n 通过 gettext Redis 存根通过connect-redis-sessions 测试骨架 代码文档 自述文件骨架 入门 什么...
JanusAdmin JanusAdmin是一个node.js http客户端,它实现了Janus WebRTC网关的整个管理界面。用法var JanusAdmin = require ( 'janus-admin' ) . JanusAdmin ;var admin = new JanusAdmin ( { url : '...
1. **Node.js**:Node.js是一个基于Chrome V8引擎的JavaScript运行环境,它允许开发者使用JavaScript进行服务器端编程。Node.js的事件驱动、非阻塞I/O模型使其在处理高并发请求时表现出色。 2. **Express.js**:...
首先,`node.js`是一个基于Chrome V8引擎的JavaScript运行环境,它允许我们在服务器端执行JavaScript代码。使用Node.js,开发者可以利用JavaScript进行全栈开发,极大地提高了开发效率。 `Express.js`是基于Node.js...
RedisStore由 Redis 支持的实现Gorilla Sessions Store。它用作go-redis客户端连接到Redis。如果你使用的是Redis 6(客户端 go-redis/v8),请安装 redisstore/v8go get github.com/rbcervilla/redisstore/v8如果你...
Together, the MongoDB database, the Express and AngularJS frameworks, and Node.js constitute the MEAN stack—a powerful platform that uses only one language, top to bottom: JavaScript. Developers and...
A Practical Guide to TPM 2.0: Using the Trusted Platform Module in the New Age of Security is a straight-forward primer for developers. It shows security and TPM concepts, demonstrating their use in ...
Using Functions in Your Code. . . . . . . . . . . . . . . . . . . . . . . . . . . . 491 Using include() and require(). . . . . . . . . . . . . . . . . . . . . . . . . . . 492 Appendix DWriting Your ...
使用 Redis 的 gorilla/sessions 会话存储后端。重新恢复 gorilla/sessions的会话存储后端- src。要求依赖于Redigo Redis 库。安装go get gopkg.in/boj/redistore.v1文档可在godoc.org上获取。有关底层接口的完整...
500行Node.js简单实现单点登录(SSO)中央授权单元和客户端 重要的 要运行这些示例,您需要在 linux 中的/etc/hosts文件中添加以下条目 127.0.0.1 sso.ankuranand.com 127.0.0.1 consumer.ankuranand.in 介绍 Web ...
./app.js - 入口点 ./package.json - npm 包描述 ./posts.js - 帖子数据访问助手 ./sessions.js - 会话数据访问助手 ./users.js - 用户数据访问助手 ./views / - html 模板 入门 npm 安装节点 app.js