2012-08-29 33 views
17

Tôi đang cố gắng tạo một ứng dụng trò chuyện dựa trên Node.js. Tôi muốn ép buộc máy chủ websocket (thư viện ws) sử dụng hệ thống phiên ExpressJS. Thật không may, tôi đã bị mắc kẹt. Các băm MemoryStore được sử dụng để lấy dữ liệu phiên khác với các ID phiên trong cookie. Ai đó có thể giải thích cho tôi những gì tôi đang làm sai?ExpressJS & Websocket & phiên chia sẻ

WebSocket mã máy chủ phần: định nghĩa đối tượng

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() {...}); 
     }); 
    }); 
}); 
} 

cửa hàng: cấu hình

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

ứng dụng:

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" 
    })); 
}); 

Một phần của mã chính:

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

Mẫu gỡ lỗi đầu ra:

- 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

đơn giản, workaround xấu xí giúp: sessionid = sessionID.match (/: [a-zA-Z0-9/+] + \ ./) [0]. slice (1, -1), nhưng tôi muốn giải quyết vấn đề này. – skorczan

+0

Cảm ơn bạn đã giải quyết vấn đề này, đã giúp tôi :) Bạn đã bao giờ tìm được giải pháp thích hợp cho điều này chưa? – Tim

Trả lời

16

tôi đã có thể làm việc này. Tôi nghĩ bạn cần phải xác định bí mật trên cookieParser thay vì lưu trữ phiên.

Ví dụ từ ứng dụng của tôi:

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

tôi thấy làm việc này cho tôi. Không chắc chắn đó là cách tốt nhất để làm điều này mặc dù. Trước tiên, hãy khởi tạo ứng dụng nhanh của bạn:

// 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); 

Bây giờ, gọi rõ ràng phần mềm trung gian phiên từ kết nối WS. Nếu bạn đang sử dụng mô-đun express-session, phần mềm trung gian sẽ tự phân tích cú pháp các cookie. Nếu không, trước tiên bạn có thể cần phải gửi nó thông qua phần mềm trung gian phân tích cú pháp cookie của bạn.

Nếu bạn đang sử dụng mô-đun websocket:

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

Nếu bạn đang sử dụng mô-đun ws:

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

Để tiện cho bạn, đây là một ví dụ làm việc đầy đủ, sử dụng express, express-sessionws:

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

Chăm sóc để giải thích các downvote? – Azmisov

+0

Một chút muộn cho bữa tiệc, nhưng mã của bạn sẽ không biên dịch. Dòng trước dấu cuối cùng thiếu một ')' –

+0

@matejkramny Cảm ơn, đã sửa đổi – Azmisov

0

Hiện tại, dưới đây là giải pháp thay thế của tôi đang hoạt động tốt. Tôi chỉ không biết đó là nhược điểm và an ninh. Tôi chỉ ngăn máy chủ nghe nếu nó không có phiên. (Share session from express-session to ws)

Tôi chưa thử nghiệm đầy đủ điều này.

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 trở lên đã thay đổi hành vi để các câu trả lời được đưa ra sẽ không hoạt động đối với các phiên bản đó. Đối với các phiên bản hiện tại, chữ ký của phương thức kết nối là [hàm (socket, request)] và socket không còn chứa tham chiếu tới request.

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

Trong phiên bản 3.2.0 của ws bạn phải làm điều đó một chút khác nhau.

full working example phân tích cú pháp phiên nhanh trong repo ws, cụ thể bằng cách sử dụng tính năng mới verifyClient.

Một bản tóm tắt rất ngắn sử dụng:

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}`) 
    }) 
})