2012-08-29 50 views
17

私はNode.jsに基づいてチャットアプリケーションを作ろうとしています。私はWebSocketサーバー(wsライブラリ)をExpressJSセッションシステムを使用するように強制したいと思います。残念ながら、私は立ち往生している。セッションのデータを取得するために使用されるMemoryStoreハッシュは、CookieのセッションIDとは異なります。誰かが私が間違っていることを私に説明することができましたか?ExpressJS&ウェブソケットとセッション共有

のWebSocketサーバコード部:

module.exports = function(server, clients, express, store) { 
    server.on('connection', function(websocket) { 
    var username; 

    function broadcast(msg, from) {...} 

    function handleMessage(msg) {...} 

    express.cookieParser()(websocket.upgradeReq, null, function(err) { 
     var sessionID = websocket.upgradeReq.cookies['sid']; 

      //I see same value in Firebug 
     console.log(sessionID); 

      //Shows all hashes in store 
      //They're shorter than sessionID! Why? 
     for(var i in store.sessions) 
      console.log(i); 

     store.get(sessionID, function(err, session) { 
       websocket.on('message', handleMessage); 

       //other code - won't be executed until sessionID in store 

       websocket.on('close', function() {...}); 
     }); 
    }); 
}); 
} 

ストアオブジェクト定義:

var store = new express.session.MemoryStore({ 
    reapInterval: 60000 * 10 
}); 

アプリ構成:メインコードの

app.configure(function() { 
    app.use(express.static(app.get("staticPath"))); 
    app.use(express.bodyParser()); 
    app.use(express.cookieParser()); 

    app.use(express.session({ 
     store: store, 
     secret: "dO_ob", 
     key: "sid" 
    })); 
}); 

パート:

var app = express(); 
var httpServer = http.createServer(app); 
var websocketServer = new websocket.Server({server: httpServer}); 
httpServer.listen(80); 

サンプルデバッグ出力:

- websocket.upgradeReq.headers.cookie "sid=s%3A64a%2F6DZ4Mab8H5Q9MTKujmcw.U8PJJIR%2BOgONY57mZ1KtSPx6XSfcn%2FQPZ%2FfkGwELkmM" 
- websocket.upgradeReq.cookies["sid"] "s:64a/6DZ4Mab8H5Q9MTKujmcw.U8PJJIR+OgONY57mZ1KtSPx6XSfcn/QPZ/fkGwELkmM" 
- i "64a/6DZ4Mab8H5Q9MTKujmcw" 
+1

シンプルな、醜い回避策が役立ちます:セッションID = sessionID.match(/:[-ZA-Z0-9/+] + \ ./)[0]。スライス(1、-1)ですが、私はこの問題を解決したいと思います。 – skorczan

+0

回避策をお寄せいただきありがとうございました:)これに適切な解決策を見つけましたか? – Tim

答えて

16

私はこの作業を取得することができました。セッションストアの代わりにcookieParserにシークレットを指定する必要があると思います。私のアプリから

例:

var app = express(); 
var RedisStore = require('connect-redis')(express); 
var sessionStore = new RedisStore(); 
var cookieParser = express.cookieParser('some secret'); 

app.use(cookieParser); 
app.use(express.session({store: sessionStore})); 


wss.on('connection', function(rawSocket) { 

    cookieParser(rawSocket.upgradeReq, null, function(err) { 
    var sessionID = rawSocket.upgradeReq.signedCookies['connect.sid']; 
    sessionStore.get(sessionID, function(err, sess) { 
     console.log(sess); 
    }); 
    }); 

}); 
14

私はこれが私のために動作しました。これを行うには最良の方法だとは思わない。まず、明示的なアプリケーションを初期化します。

// whatever your express app is using here... 
var session = require("express-session"); 
var sessionParser = session({ 
    store: session_store, 
    cookie: {secure: true, maxAge: null, httpOnly: true} 
}); 
app.use(sessionParser); 

ここで、セッションミドルウェアをWS接続から明示的に呼び出します。 express-sessionモジュールを使用している場合、ミドルウェアはCookieを単独で解析します。それ以外の場合は、まずクッキー解析ミドルウェア経由で送信する必要があります。あなたはwsモジュール使用している場合

ws.on("request", function(req){ 
    sessionParser(req.httpRequest, {}, function(){ 
     console.log(req.httpRequest.session); 
     // do stuff with the session here 
    }); 
}); 

あなたがwebsocketモジュールを使用している場合expressを使用して、

あなたの便宜のため
ws.on("connection", function(req){ 
    sessionParser(req.upgradeReq, {}, function(){ 
     console.log(req.upgradeReq.session); 
     // do stuff with the session here 
    }); 
}); 

、ここで完全に実施例であるが、 express-session,ws

var app = require('express')(); 
var server = require("http").createServer(app); 
var sessionParser = require('express-session')({ 
    secret:"secret", 
    resave: true, 
    saveUninitialized: true 
}); 
app.use(sessionParser); 

app.get("*", function(req, res, next) { 
    req.session.working = "yes!"; 
    res.send("<script>var ws = new WebSocket('ws://localhost:3000');</script>"); 
}); 

var ws = new require("ws").Server({server: server}); 
ws.on("connection", function connection(req) { 
    sessionParser(req.upgradeReq, {}, function(){ 
     console.log("New websocket connection:"); 
     var sess = req.upgradeReq.session; 
     console.log("working = " + sess.working); 
    }); 
}); 

server.listen(3000); 
+4

気をつけてくださいdownvoteを説明する? – Azmisov

+0

少し遅れていますが、コードはコンパイルされません。最後の行に ')'がありません。 –

+0

@matejkramnyありがとう、今修正されました – Azmisov

0

現在、以下は私の問題を解決するためのものです。私はそれが欠点とセキュリティであることを知りません。私はちょうどそれがセッションを持っていない場合、サーバーがリッスンするのを防ぎます。 (Share session from express-session to ws

私はこれを十分にテストしていません。

var http = require('http'); 
var express = require('express'); 
var expressSession = require('express-session'); 
var router = express.Router(); 
var app = express(); 

const server = http.createServer(app); 

router.get('/', function(req, res, next) { 
    if(req.session.user_id) { 
     // Socket authenticated 
     server.listen(8080, function listening(){}); 
    } 
}); 
0

WS v3.0.0以上では、これらのバージョンでは指定した回答がそのまま動作しないように動作が変更されています。現在のバージョンでは、接続メソッドのシグネチャは[function(socket、request)]であり、ソケットはもはや要求への参照を含んでいません。

ws.on(
    'connection', 
    function (socket, req) 
    { 
     sessionParser(
      req, 
      {}, 
      function() 
      { 
       console.log(req.session); 
      } 
     ); 
    } 
); 
0

wsのバージョン3.2.0では、少し違うようにする必要があります。

具体的には新機能verifyClientを使用して、wsレポには、高速セッション解析のfull working exampleがあります。

非常に簡単な使用方法の概要:

const sessionParser = session({ 
    saveUninitialized: false, 
    secret: '$eCuRiTy', 
    resave: false 
}) 

const server = http.createServer(app) 
const wss = new WebSocket.Server({ 
    verifyClient: (info, done) => { 
    console.log('Parsing session from request...') 
    sessionParser(info.req, {},() => { 
     console.log('Session is parsed!') 
     done(info.req.session.userId) 
    }) 
    }, 
    server 
}) 

wss.on('connection', (ws, req) => { 
    ws.on('message', (message) => { 
    console.log(`WS message ${message} from user ${req.session.userId}`) 
    }) 
}) 
関連する問題