2

接続されているすべてのクライアントをオブジェクトに保存しようとしています。しかし、私が考えたように、接続されているクライアントはすべて同じ ID を持っています。したがって、オブジェクトconnectionsにすべてのソケットが接続されている場合、メッセージを送信しようとすると、connections['mac']私から送信されたように画面に表示されます。認証コードは次のとおりです。

app.post('/auth', function(req, res){   // routes.auth(hash, db, io, pseudoArray, connections)
    var username = req.body.username,
        password = req.body.password;
    if (username != "" && password != ""){
        authenticate(username, password, db, hash, function(err, user){
            if (user) {
                // Regenerate session when signing in
                // to prevent fixation 
                console.log('user authenticated');
                req.session.regenerate(function(){
                    req.session.user = user.name;
                    req.session.success = 'Authenticated as ' + user.name
                    + ' click to <a href="/logout">logout</a>. '
                    + ' You may now access <a href="/restricted">/restricted</a>.';

                    io.sockets.on('connection', function (socket) {
                        socket.set('pseudo', req.session.user, function(){
                            pseudoArray.push(req.session.user);
                            var sessionuser = req.session.user;
                            socket.emit('pseudoStatus', 'ok');
                            connections[req.session.user] = socket;
                            console.log("user " + req.session.user + " connected");
                        });
                    });
                    res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true });
                    res.redirect('home');
                });
            } else {
                console.log('auth failed');
                req.session.error = 'Authentication failed, please check your '
                    + ' username and password.'
                    + ' (use "tj" and "foobar")';
                res.redirect('login');
            }
        }); 
    } else {
        res.redirect('connect');
    }
});

メッセージを他のクライアントに送信するコード:

exports.addfriend = function(connections, io){
    return function(req, res){
        // var collection = db.get('go1');
        var username = req.session.user;
        var friend = req.body.name;
        console.log(connections[''+friend+'']);
        connections[''+friend+''].emit('addRequest', username);
        return;
    }
}

以前にルート ファイルにこの認証コードがありましたが、これを app.js から実行する必要があると考えています。私はそれをしましたが、それでも私が望むようには機能しません。誰かが私に欠けているものを教えてもらえますか?

4

2 に答える 2

5

コードの問題は、HTTP ルートの 1 つに Socket.IO 着信接続ハンドラーがあることです。つまり、単一の Socket.IO 接続ハンドラーのみを持つ必要があるという事実に加えて、ルートがアクセスされた後にのみハンドラーが適用されます。

必要なのは、HTTP ハンドラーと Socket.IO ハンドラーを分離することです。セッションを使用しているため、Socket.IO が承認を処理できるようにします。

まず、ソケット ハンドラーを HTTP ハンドラーの外に移動します。

app.post('/', handler);
io.sockets.on('connection', handler);

次に、Socket.IO 承認設定を定義して、Express からセッション オブジェクトを取得します。express.cookieParser()セッションとセッションストアがあるため、使用していると仮定すると、それらを外部参照する必要があります。

var MemoryStore = express.session.MemoryStore;

var session_key = 'express.sid';
var session_secret = 'for signed cookies';
var session_store = new MemoryStore();

var cookieParser = express.cookieParser(session_secret);

app.use(cookieParser);
app.use(express.session({
  secret: session_secret,
  store: session_store,
  key: session_key
});

セッション オブジェクトと Cookie パーサーにアクセスできるようになったので、承認設定を定義できます。

io.set('authorization', function(handshake, callback) {
  if (handshake.headers.cookie) {
    cookieParser(handshake, null, function(err) {
      // Use depends on whether you have signed cookies
      // handshake.sessionID = handshake.cookies[session_key];
      handshake.sessionID = handshake.signedCookies[session_key];

      session_store.get(handshake.sessionID, function(err, session) {
        if (err || !session) {
          callback('Error or no session.', false);
        } else {
          handshake.session = session;
          callback(null, true);
        }
      });
    });
  } else {
    callback('No session cookie found.', false);
  }
});

このコードが行うことは、クライアントがセッション Cookie を持っているかどうかをチェックすることです。そうでない場合、Socket.IO 接続は承認されません。存在する場合は、Cookie を解析し、関連するセッションを見つけて、そのセッションをソケットに保存します。これで、ソケットによってセッション プロパティにアクセスできるようになりました。

app.post('/', function(req, res) {
  req.session.user = 'genericusername';
  res.send(200);
});

io.sockets.on('connection', function(socket) {
  var session = socket.handshake.session;
  session.user // genericusername
});

コードに関しては、次のようになります。

var http = require('http');
var express = require('express');
var app = express();

var server = http.createServer(app);
var io = require('socket.io').listen(server);

var MemoryStore = express.session.MemoryStore;

var session_key = 'express.sid';
var session_secret = 'for signed cookies';
var session_store = new MemoryStore();

var cookieParser = express.cookieParser(session_secret);

app.use(cookieParser);
app.use(express.session({
  secret: session_secret,
  store: session_store,
  key: session_key
});

ルート ハンドラ:

app.post('/auth', function(req, res) {
  var username = req.body.username,
  var password = req.body.password;

  if (username != '' && password != '') {
    authenticate(username, password, db, hash, function(err, user) {
      if (user) {
        req.session.regenerate(function() {
          req.session.user = user.name;
          req.session.success = 'Authenticated as ' + user.name + ' click to <a href="/logout">logout</a>. You may now access <a href="/restricted">/restricted</a>.';
          res.cookie('rememberme', '1', {
            maxAge: 900000,
            httpOnly: true
          });
          res.redirect('/home');
        });
      } else {
        req.session.error = 'Authentication failed, please check your username and password. (use "tj" and "foobar")';
        res.redirect('/login');
      }
    }); 
  } else {
    res.redirect('/connect');
  }
});

そして、Socket.IO 構成:

io.set('authorization', function(handshake, callback) {
  if (handshake.headers.cookie) {
    cookieParser(handshake, null, function(err) {
      // Use depends on whether you have signed cookies
      // handshake.sessionID = handshake.cookies[session_key];
      handshake.sessionID = handshake.signedCookies[session_key];

      session_store.get(handshake.sessionID, function(err, session) {
        if (err || !session) {
          callback('Error or no session.', false);
        } else {
          handshake.session = session;
          callback(null, true);
        }
      });
    });
  } else {
    callback('No session cookie found.', false);
  }
});

io.sockets.on('connection', function(socket) {
  var session = socket.handshake.sessionl
  socket.set('pseudo', session.user, function() {
    socket.emit('pseudoStatus', 'ok');
    connections[session.user] = socket;
  });
});
于 2013-10-14T15:33:21.780 に答える