3

私のアプリのセッション データはnode-client-sessionsで処理され (「安全なクライアント側セッションを使用してシンプルでスケーラブルな Node.JS アプリケーションを構築する」で提案されているように)、いくつかのリアルタイム機能を処理するためにsocket.io (websockets) が用意されました。 . ハンドシェイクのセッション データによって、ログインしているユーザーを認証したいと思います。しかし、socket.io はハンドシェイク時にこのhandshakeDataオブジェクトを提供し、リクエスト オブジェクトを完全には公開しません。リクエストのセッション プロパティにアクセスする必要があります。何か案は?

私はexpressjs(nodejs)を使用しています。

アップデート

@LaurentPerrin の回答にインスパイアされて、クライアント セッション ソースに飛び込み、デコードおよびエンコード関数が公開されていることを発見しました。セッション オブジェクトを直接いじるほど簡単ではないかもしれませんが、これまでのところ非常に効果的です。

私のコード、これまでのところ:

/*jslint node: true, es5: true, nomen: true, unparam: true */

'use strict';

var encode = require('client-sessions').util.encode,
    decode = require('client-sessions').util.decode,
    cookie = require('cookie'),

    cookieSettings = require('./persistors/cookieSettings'),

    authorized = {
        'me@domain.com': 1
    };

module.exports = function websocket(io) {
    io.set('authorization', function (handshakeData, callback) {
        var session_data;
        if (!handshakeData.headers.cookie) {
            callback({
                status: 'forbidden',
                reason: 'no session',
                source: 'socket_io'
            }, false);
            return;
        }
        session_data = decode(cookieSettings, cookie.parse(handshakeData.headers.cookie).session).content;
        if (authorized[session_data.email]) {
            handshakeData.session_data = session_data;
            callback(null, true);
        } else {
            // callback({
            //     status: 'forbidden',
            //     reason: 'unauthorized',
            //     source: 'socket_io'
            // }, false);
            callback(null, false);
        }
        return;
    });
    io.set('transports', ['websocket', 'flashsocket']);
    io.sockets.on('connection', function (socket) {
        console.log('connected')
        socket.on('credenciamento', function (data) {
            console.log(socket.handshake.session_data.email);
            socket.broadcast.emit('credenciamento', {
                inscrito_id: data.inscrito_id
            });
        });
    });
};

それは決して完全ではありません。しかし、承認部分はうまく機能しているようです。=)

さて、コールバック関数について。最初は @LaurentPerrin のように使用し、false 応答でオブジェクトを渡しました。しかし、それは警告を生成します。Socket.io は、エラーが発生したと見なします。

warn - handshake error [object Object]

したがって、2番目の瞬間に、null承認しないときに最初のパラメーターとして渡しました。

info - handshake unauthorized

socket.io がそれぞれを理解する方法を考えると、意味的には 2 番目の方法の方が正しいようです。=)

私は2番目の方法を選択します。自分で選んでください。

4

1 に答える 1

4

全く同じかどうかはわかりませんが、私の場合で書いてみました。バージョンの問題を避けるために、明示的な依存関係で直接必要であることに注意してください。

var cookie = require('express/node_modules/cookie'),
    parseSignedCookie = require('express/node_modules/connect').utils.parseSignedCookie,
    parseJSONCookie = require('express/node_modules/connect').utils.parseJSONCookie;

…

io.set('authorization', authorizeSocket);

…

function authorizeSocket(handshake, done) {
  if (!handshake.headers.cookie)
    return done({status: 'forbidden', reason: 'no session', source: 'socket_io'}, false);

  var cookies = cookie.parse(handshake.headers.cookie),
      signed = cookies['your_session_cookie'];

  if (!signed)
    return done({status: 'forbidden', reason: 'tampered cookie', source: 'socket_io'}, false);

  var raw = parseSignedCookie(signed, 'your_session_secret'),
  json = parseJSONCookie(raw);

  if (!json || !json.passport || !json.passport.user)
    return done({status: 'forbidden', reason: 'bad session', source: 'socket_io'}, false);

  // finally...
  var user = json.passport.user;

  handshake.user = user;

  done(null, true);
}
于 2013-08-27T21:18:26.553 に答える