PHP,nodeJS和会话

我有一个经典的Apache服务器提供的PHP文件,和一个nodeJS服务器(与socket.io,但没有快速/连接)用于实时事件pipe理该PHP网站。 我有时需要authentication连接到nodeJS服务器的客户端,但是当用户重新加载页面时,这个authentication会丢失,因为它也重新加载了socket.io客户端(我在服务器上存储了套接字ID,每次刷新都会丢失)
问题是:有没有办法保持连接在socket.io,或链接的Apache PHP会话和nodeJS服务器的方式? 或者也许一种方法来保持使用cookie的身份validation(知道我必须存储敏感数据,如用户密码和密钥)?

您可以在PHP中使用memcached作为会话存储处理程序 。 Memcached是一个简单的键值存储,可以通过TCP访问; 有一个memcached模块可​​用于Node.js。

PHP通过使用会话ID作为密钥将会话存储在memcached中。 存储在memcached中的会话数据(值)是一个序列化的PHP对象, 略有扭曲 。 您可以阅读更多关于这个不寻常的序列化在SO问题“parsingPHP中的PHP会话” 。 幸运的是,已经有一个NPM模块: php-unserialize


现在的方法。

假设

  • memcached可以在127.0.0.1:11211访问
  • php.ini(或php.d / memcache.ini)configuration为: session.save_handler='memcached'session.save_path='tcp://127.0.0.1:11211'
  • 你已经安装了所需的NPM模块(2): npm install memcached php-unserialize
  • 你可以使用CLI

准备

首先,为了获得一些testing数据,保存下面的PHP脚本( s.php ):

 <?php session_start(); $_SESSION['some'] = 'thing'; echo session_id()."\n"; print_r($_SESSION); 

php s.php执行它,它应该把东西放在标准输出:

 74ibpvem1no6ssros60om3mlo5 Array ( [some] => thing ) 

好的,现在我们知道会话ID( 74ibpvem1no6ssros60om3mlo5 ),并确认会话数据已设置。 为了确认它是在memcached中,你可以运行memcached-tool 127.0.0.1:11211 dump ,它提供了一个已知键值对的转储,例如我有两个在我的testing平台:

 Dumping memcache contents Number of buckets: 1 Number of items : 3 Dumping bucket 2 - 3 total items add 74ibpvem1no6ssros60om3mlo5 0 1403169638 17 some|s:5:"thing"; add 01kims55ut0ukcko87ufh9dpv5 0 1403168854 17 some|s:5:"thing"; 

到目前为止,我们有1)在php中创build会话ID,2)在memcached中从php存储会话数据,3)通过CLI确认数据存在。

用Node.js检索

这部分其实很简单。 大部分重任已经由NPM模块完成了。 我制作了一个通过CLI运行的Node.js脚本,但是你得到了这个图片:

 var Memcached = require('memcached'); var PHPUnserialize = require('php-unserialize'); var mem = new Memcached('127.0.0.1:11211'); // connect to local memcached var key = process.argv[2]; // get from CLI arg console.log('fetching data with key:',key); mem.get(key,function(err,data) { // fetch by key if ( err ) return console.error(err); // if there was an error if ( data === false ) return console.error('could not retrieve data'); // data is boolean false when the key does not exist console.log('raw data:',data); // show raw data var o = PHPUnserialize.unserializeSession(data); // decode session data console.log('parsed obj:',o); // show unserialized object }); 

假设上述内容保存为m.js ,则可以使用node m.js 74ibpvem1no6ssros60om3mlo5运行,该node m.js 74ibpvem1no6ssros60om3mlo5将输出如下所示的内容:

 fetching data with key: 74ibpvem1no6ssros60om3mlo5 raw data: some|s:5:"thing"; parsed obj: { some: 'thing' } 

警告/陷阱

我的一个PHP应用程序在会话值中存储了一些二进制数据(即encryption的),但是键和正常的会话对象保持不变(如上面的例子)。 在这种情况下, memcached-tool <host:port> dump将格式错误的序列化会话string打印到stdout; 我认为这可能是孤立的标准,但我错了。 当使用PHPUnserialize.unserializeSession ,它在parsing数据时也遇到了问题 (由|分隔)。 我在网上尝试了一些其他的会话反序列化方法,但没有成功。 我会认为memcached在内部维护正确的数据,因为它与原生的PHP会话保存处理程序一起工作,所以,在写这篇文章的时候,我不太确定是否是反序列化方法,或者memcached NPM模块是简单的没有正确的检索/解释数据。 当使用ascii或utf-8等非二进制数据时,它应该按照预期工作。

如果您的项目在数据库中存储会话 – 有些可以 – 那么您可以考虑使用数据库作为传输介质。

如果在你的特定情况下分析显示承诺,那么可以使用node-mysql(或类似的) – 看到这个: 链接

虽然线程是老,我想推荐我用于我的项目。 您可以使用Redis进行会话处理,而不是memcached。 我已经使用phpredis作为php redis客户端。而不是将会话存储到文件,您可以保存在Redis中。 大部分繁重工作将由apache完成。 对于每个请求,apache都会将会话值附加到cookie中,并且从每个请求中读取会话值并进行validation。

将php会话保存到redis所需的设置也非常简单。

session.save_handler = redis session.save_path =“tcp:// host1:6379?weight = 1,tcp:// host2:6379?weight = 2&timeout = 2.5,tcp:// host3:6379?weight = 2”

这就是它。这将使PHP保存到redis而不是文件的会话。 这也会将存储在文件中的会话移动到redis。