PHP、NodeJ和会话
我有一个提供php文件的经典apache服务器,还有一个用于php网站上实时事件管理的nodeJS服务器(带有socket.io,但不是whithout express/connect)。有时我需要对连接到nodeJS服务器的客户端进行身份验证,但当用户重新加载页面时,这种身份验证将丢失,因为它也会重新加载socket.io客户端(我将套接字ID存储在服务器上,每次刷新时都会丢失)PHP、NodeJ和会话,php,node.js,sockets,session,keep-alive,Php,Node.js,Sockets,Session,Keep Alive,我有一个提供php文件的经典apache服务器,还有一个用于php网站上实时事件管理的nodeJS服务器(带有socket.io,但不是whithout express/connect)。有时我需要对连接到nodeJS服务器的客户端进行身份验证,但当用户重新加载页面时,这种身份验证将丢失,因为它也会重新加载socket.io客户端(我将套接字ID存储在服务器上,每次刷新时都会丢失) 问题是:在socket.io中有没有保持连接活动的方法,或者有没有链接ApachePHP会话和nodeJS服务器的
问题是:在socket.io中有没有保持连接活动的方法,或者有没有链接ApachePHP会话和nodeJS服务器的方法?或者是一种使用cookies(知道我必须存储敏感数据,如用户密码和密钥)保持身份验证的方法?您可以使用。Memcached是一个简单的键值存储,可以通过TCP访问;有一个问题 PHP使用会话id作为键将会话存储在memcached中。存储在memcached中的会话数据(值)是一个序列化的PHP对象,稍微有点扭曲。您可以在上阅读有关此不寻常序列化的更多信息。幸运的是,已经有了一个NPM模块:
现在来看看怎么做 假设
- memcached可在127.0.0.1:11211访问
- php.ini(或php.d/memcache.ini)配置为:
和session.save\u handler='memcached'
session.save\u path='1!'tcp://127.0.0.1:11211“
- 您已经安装了所需的NPM模块(2):
NPM install memcached php unserialize
- 你对CLI没问题
s.php
):
好的,现在我们知道了会话id(74ibpvem1no6ssros60om3mlo5
),并确认会话数据已设置。要确认它在memcached中,您可以运行memcached tool 127.0.0.1:11211 dump
,它提供已知键:值对的转储,例如,我的测试台上有两个:
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中创建了会话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
,则可以使用节点m.js 74ibpvem1no6ssros60om3mlo5
运行,该节点将输出如下内容:
fetching data with key: 74ibpvem1no6ssros60om3mlo5
raw data: some|s:5:"thing";
parsed obj: { some: 'thing' }
警告/陷阱
我的一个PHP应用程序将一些二进制数据存储在会话值中(即加密),但密钥和正常会话对象保持不变(如上面的示例所示)。在这种情况下,
memcached tool dump
将格式错误的序列化会话字符串打印到stdout;我想这可能是孤立于stdout的,但我错了在使用PHPUnserialize.unserializeSession
时,解析数据时也遇到问题(由|
分隔)。我在网上尝试了其他一些会话反序列化方法,但没有成功。我假设memcached在内部维护正确的数据,因为它与本机PHP会话保存处理程序一起工作,所以在撰写本文时,我不太确定是反序列化方法还是memcached NPM模块没有正确检索/解释数据。当坚持使用非二进制数据(如ascii或utf-8)时,它应该按预期工作。我认为此链接将对您有所帮助
< p>如果您的项目在数据库中存储会话-一些DO,那么您可以考虑使用数据库作为传输介质。
如果对您的特定案例的分析显示有希望,那么可以使用节点mysql(或类似的),请参见:虽然线程很旧,但我想推荐我在项目中使用的线程。 除了memcached,您还可以使用Redis进行会话处理。 我使用的是php redis客户端。您可以在redis中保存会话,而不是将会话存储到文件中。大部分重物将由阿帕奇完成。对于每个请求,apache都会将会话值附加到cookie中,并从每个请求中读取会话值并进行验证 将php会话保存到redis所需的设置也非常简单 session.save_handler=redis session.save_路径=”tcp://host1:6379?weight=1, tcp://host2:6379?weight=2&timeout=2.5, tcp://host3:6379?weight=2" 就是这样。这将使php将会话保存到redis而不是文件。这也会将存储在文件中的会话移动到redis。的答案帮助我完成身份验证,这是我已经采取的方法。谢谢你 我发布的原因是在使用时出于某种原因:
var PHPUnserialize = require('php-unserialize');
不断地给我错误
SyntaxError: String length mismatch
我不知道为什么?我写了一个函数,为我做这项工作,并希望分享,以防它可能会帮助其他人
function Unserialize(data){
var result = {};
if(data !== undefined){
var preg = data.replace(/(^|s:[0-9]+:)|(^|i:)|(^|b:)|(")|(;$)/g,'').split(';');
var a = [];
preg.forEach(function(value){
a.push(value.split('|'));
});
var b = [];
a.forEach(function(value){
if(Array.isArray(value)){
Array.prototype.push.apply(b, value);
}else{
b.push(value);
}
});
var arr_A = [];
var arr_B = [];
b.forEach(function(value, k){
if(k % 2 == 0){
arr_A.push(value);
}else{
arr_B.push(value);
}
});
if (arr_A == null) return {};
for (var i = 0, l = arr_A.length; i < l; i++) {
if (arr_B) {
result[arr_A[i]] = arr_B[i];
} else {
result[arr_A[i][0]] = arr_A[i][1];
}
}
}
return result;
}
您应该能够很容易地修改正则表达式以满足您的需要 在PHP中使用memcached作为会话存储处理程序,然后使用-现在您所需要的只是会话标识符。这似乎是可行的,但是PHP如何在memcached中存储会话呢?密钥是会话id,值是$\u会话变量的JSON编码字符串还是…?您可以维护一个包含登录用户的单独数组。使用套接字ID不是解决方案,因为刷新时,套接字会断开连接。如果用户注销,则会触发一个事件,从该数组中删除userdata。但要注意用户在未注销的情况下关闭浏览器的情况。您的数组可能会变得太大,包含冗余数据OK,所以我现在的位置是:在设置memcached之后,我通过PHPSESSID cookie(在socket.io授权中)获得了PHP会话ID。但是我无法保存这个php会话ID(将其保存在handshake.session\u ID中不起作用,我无法获取我的
SyntaxError: String length mismatch
function Unserialize(data){
var result = {};
if(data !== undefined){
var preg = data.replace(/(^|s:[0-9]+:)|(^|i:)|(^|b:)|(")|(;$)/g,'').split(';');
var a = [];
preg.forEach(function(value){
a.push(value.split('|'));
});
var b = [];
a.forEach(function(value){
if(Array.isArray(value)){
Array.prototype.push.apply(b, value);
}else{
b.push(value);
}
});
var arr_A = [];
var arr_B = [];
b.forEach(function(value, k){
if(k % 2 == 0){
arr_A.push(value);
}else{
arr_B.push(value);
}
});
if (arr_A == null) return {};
for (var i = 0, l = arr_A.length; i < l; i++) {
if (arr_B) {
result[arr_A[i]] = arr_B[i];
} else {
result[arr_A[i][0]] = arr_A[i][1];
}
}
}
return result;
}
var PHPUnserialize = Unserialize;
memcached.get(key, function(err, data){
var memData = PHPUnserialize(data);
console.log(memData.is_logged_in);
});