首页 文章

如何使用redis,express和socket.io让会话正常工作?

提问于
浏览
9

所以我试图让Sessions在我的socket.on('connection',...)中工作 . 我正在尝试使用最新版本:Socket.io - 0.9.13,Express - 3.1.0和最新版本其他模块 .

无论如何,我尝试使用两个模块'connect-redis ' and ' session.socket.io',他们都有类似的问题 .

在我的代码中我有2个redis商店(socketio.RedisStore和require('connect-redis')(快递)),现在这个程序都运行正常,但因为express和socket.io需要共享会话数据,我想知道是否此设置将正确使用会话?会话存储需要与express / socketio相同吗?对我来说有点灰色区域,因为2 RedisStore将在后台使用相同的数据库?

我曾尝试在两个地方使用socket.io redisStore或connect-redis redisStore,但socket.io不喜欢connect-redis redisStore和express不喜欢socketio.redisStore .

如果我使用connect-redis RedisStore,那么socket.io/lib/manager.js抱怨:this.store.subscribe(... TypeError Object#没有方法'subscribe'

如果我使用socketio.RedisStore然后表达/ node_modules / connect / lib / middleware / session.js抱怨:TypeError:Object#没有方法'get'

*注意我宁愿让session.socket.io插件工作,但是当我使用该插件进行相同的设置时,表达(也)抱怨:TypeError:Object#没有方法'get'

所以我可以使用2个不同的RedisStore进行会话,或者我是否需要以某种方式让一个或另一个为两者工作,如果是这样,任何关于如何修复的想法?

我当前的代码如下所示:

var
    CONST = {
        port: 80,
        sessionKey: 'your secret sauce'
    };

var 
    redis = require('redis');

var 
    express = require('express'),
    socketio = require('socket.io'),
    RedisStore = require('connect-redis')(express);

var 
    redisStore = new RedisStore(),
    socketStore = new socketio.RedisStore();

var 
    app = express(),
    server = require('http').createServer(app),
    io = socketio.listen(server);

app.configure(function(){
    app.use(express.cookieParser( CONST.sessionKey ));
    app.use(express.session({ secret: CONST.sessionKey, store: redisStore }));
    app.use(express.static(__dirname + '/test'));
    app.get('/', function (req, res) {res.sendfile(__dirname + '/test/' + 'index.htm');});
});

io.configure(function(){
    io.set('log level', 1);
    io.enable('browser client minification');
    io.enable('browser client etag');
    io.enable('browser client gzip');
    io.set('store', socketStore);
});

io.sockets.on('connection', function(socket){
    socket.emit('message', 'Test 1 from server')
});

server.listen( CONST.port );

console.log('running...');

2 回答

  • 4

    io.configure 内,您必须将套接字与http会话链接 .

    这是一段提取cookie的代码(这是使用socket.io和 xhr-polling ,我不知道这是否适用于websocket,虽然我怀疑它会起作用) .

    var cookie = require('cookie');
    var connect = require('connect');
    
    var sessionStore = new RedisStore({
      client: redis // the redis client
    });
    
    socketio.set('authorization', function(data, cb) {
      if (data.headers.cookie) {
        var sessionCookie = cookie.parse(data.headers.cookie);
        var sessionID = connect.utils.parseSignedCookie(sessionCookie['connect.sid'], secret);
        sessionStore.get(sessionID, function(err, session) {
          if (err || !session) {
            cb('Error', false);
          } else {
            data.session = session;
            data.sessionID = sessionID;
            cb(null, true);
          }
        });
      } else {
        cb('No cookie', false);
      }
    });
    

    然后您可以使用以下方式访问会话:

    socket.on("selector", function(data, reply) {
      var session = this.handshake.session;
      ...
    }
    

    这还有一个额外的好处,它检查有一个有效的会话,所以只有您登录的用户可以使用套接字 . 但是,您可以使用不同的逻辑 .

  • 4

    看看你的最后一个注释(将无法使用redis在多个进程上共享其状态)我遇到了同样的问题并找到了解决方案:

    var express = require("express.io");
    var swig = require('swig');
    var redis = require('redis');
    var RedisStore = require('connect-redis')(express);
    
    workers = function() {
        var app = express().http().io();
    
        app.use(express.cookieParser());
        app.use(express.session({
            secret: 'very cool secretcode',
            store: new RedisStore({ client: redis.createClient() })
        }));
    
        app.io.set('store', new express.io.RedisStore({
            redisPub: redis.createClient(),
            redisSub: redis.createClient(),
            redisClient: redis.createClient()
        }));
    
    
        app.get('/', function(req, res) {
            res.render('index');
        });
    
        app.listen(3000);
    
    
        app.io.route('ready', function(req){
            //setup session stuff, use session stuff, etc.  Or make new routes
        });
    };
    
    cluster = require('cluster');
    numCPUs = require('os').cpus().length;
    
    if (cluster.isMaster)
    {
        for (var i = 0; i < numCPUs; i++)
        {
            cluster.fork();
        }
    }
    else
    {
        workers();
    }
    

相关问题