9

したがって、sessions を socket.on('connection', ...) 内で機能させようとしています。最近のバージョンを使用してこれを機能させようとしています: Socket.io - 0.9.13、Express - 3.1.0 および最新バージョン他のモジュールの。

とにかく、「connect-redis」と「session.socket.io」の両方のモジュールを使用してみましたが、どちらも同様の問題を抱えています。

私のコードには 2 つの redis ストア (socketio.RedisStore と require('connect-redis')(express)) があり、このプログラムはすべて正常に実行されるようになりましたが、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 # has no method 'subscribe'

socketio.RedisStore を使用すると、express/node_modules/connect/lib/middleware/session.js が文句を言います: TypeError: Object # has no method 'get'

* 注: session.socket.io プラグインを動作させたいのですが、そのプラグインで同じセットアップを行うと、(また) 表現すると、「TypeError: Object # has no method '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...');
4

2 に答える 2

4

の内部ではio.configure、ソケットをhttpセッションにリンクする必要があります。

これがCookieを抽出するコードです(これはsocket.ioを使用しています。これがWebSocketで機能するxhr-pollingかどうかはわかりませんが、機能すると思われます)。

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;
  ...
}

これには、有効なセッションがあることを確認するという追加の利点もあるため、ログインしているユーザーのみがソケットを使用できます。ただし、別のロジックを使用できます。

于 2013-03-02T01:31:15.583 に答える
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();
}
于 2013-11-16T03:46:20.280 に答える