socket.io và phiên?


95

Tôi đang sử dụng khung thể hiện. Tôi muốn truy cập dữ liệu phiên từ socket.io. Tôi đã thử express dynamicHelpers với dữ liệu client.listener.server.dynamicViewHelpers, nhưng tôi không thể lấy dữ liệu phiên. Có một cách đơn giản để làm điều này? Vui lòng xem mã

app.listen(3000);

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

io.on('connection', function(client){
    // I want to use session data here
    client.on('message', function(message){
        // or here
    });
    client.on('disconnect', function(){
        // or here
    }); 
});

5
Hoặc có thể sử dụng bài đăng RẤT THÚ VỊ này
Fabiano Soriani.

3
@FabianoPS - sẽ không hoạt động nữa - kết nối không còn cung cấp phương thức parseCookie mà điều này dựa vào.
UpTheCreek

1
@UpTheCreek - Vì kết nối không sử dụng phương thức parseCookie nữa, làm sao điều này có thể thực hiện được?
Aust

@Aust - Câu hỏi hay, tôi không biết cách tiếp cận tốt nhất bây giờ là gì. Đây thực sự là một IMO lộn xộn. Thật khó chịu là hầu hết các cuộc thảo luận về cách giải quyết cũng được đưa ra trên socket.io (không phải ai cũng đang sử dụng socket.io!). Hiện có một hàm parseSignedCookie, nhưng nó cũng riêng tư, vì vậy nó cũng có nguy cơ phá vỡ các thay đổi.
UpTheCreek

2
Đối với các phiên bản mới hơn của Socket.IO (1.x) và Express (4.x) kiểm tra câu hỏi SO này: stackoverflow.com/questions/25532692/...
pootzko

Câu trả lời:


68

Điều này sẽ không hoạt động đối với các ổ cắm đi qua quá trình truyền tải flashsocket (nó không gửi cho máy chủ các cookie cần thiết) nhưng nó hoạt động một cách đáng tin cậy cho mọi thứ khác. Tôi chỉ vô hiệu hóa quá trình vận chuyển flashsocket trong mã của mình.

Để làm cho nó hoạt động, ở phía express / connect, tôi xác định rõ ràng session store để tôi có thể sử dụng nó bên trong socket:

MemoryStore = require('connect/middleware/session/memory'),
var session_store = new MemoryStore();
app.configure(function () {
  app.use(express.session({ store: session_store }));
});

Sau đó, bên trong mã socket của tôi, tôi bao gồm khung kết nối để tôi có thể sử dụng phân tích cú pháp cookie của nó để lấy ra connect.sid từ cookie. Sau đó, tôi tìm kiếm phiên trong cửa hàng phiên có kết nối đó như sau:

var connect = require('connect');
io.on('connection', function(socket_client) {
  var cookie_string = socket_client.request.headers.cookie;
  var parsed_cookies = connect.utils.parseCookie(cookie_string);
  var connect_sid = parsed_cookies['connect.sid'];
  if (connect_sid) {
    session_store.get(connect_sid, function (error, session) {
      //HOORAY NOW YOU'VE GOT THE SESSION OBJECT!!!!
    });
  }
});

Sau đó, bạn có thể sử dụng phiên này nếu cần.


3
Dường như socket_client.request đã được gỡ bỏ trong các phiên bản mới nhất của socket.io-nút
Nghệ thuật

6
Hãy cẩn thận ... có những quy ước mới để làm điều này ngay bây giờ ... Tôi khuyên bạn nên sử dụng xác thực Socket.IO để thay thế. Xem bài đăng từ @Jeffer
BMiner

2
Thật không may, điều này sẽ không hoạt động nữa - parseCookie không còn là một phần của các utils kết nối. Rõ ràng nó không bao giờ là một phần của api công cộng. Có một sự thay thế lộn xộn - parseSignedCookie, nhưng điều này cũng là riêng tư, vì vậy tôi đoán nó cũng có nguy cơ biến mất ..
UpTheCreek

Bây giờ tôi đang suy nghĩ về điều này .... tại sao không chỉ đặt cửa hàng cho cookie và cửa hàng cho ổ cắm vào cùng một cửa hàng?
James

34

Giải pháp mô-đun Socket.IO-session khiến ứng dụng bị tấn công XSS bằng cách làm lộ ID phiên ở cấp ứng dụng khách (kịch bản).

Thay vào đó, hãy chọn giải pháp này (đối với Socket.IO> = v0.7). Xem tài liệu tại đây .


1
@Jeffer - giải pháp thứ hai đó sẽ không hoạt động nữa với phiên bản kết nối hiện tại.
UpTheCreek

2
-1 socket.iolà những gì đang hiển thị ID phiên, không phải mô-đun đó. Đây không phải là vấn đề lớn vì dù sao thì ID phiên cũng được lưu trữ phía máy khách trong cookie ... Ngoài ra, hướng dẫn đó không hoạt động với phiên bản Express mới nhất.
Aust

1
liên kết giải pháp của bạn chỉ đơn giản là chuyển hướng đến socket.iotrang github ..?
TJ

8

Tôi đề nghị không nên phát minh lại hoàn toàn bánh xe. Công cụ bạn cần đã là một gói npm. Tôi nghĩ đây là những gì bạn cần: session.socket.io Tôi đang sử dụng nó trong những ngày này và tôi đoán nó sẽ rất hữu ích !! Liên kết express-session với lớp socket.io sẽ có rất nhiều lợi thế!


6
Dưới đây là một mô-đun được cập nhật mà hỗ trợ cho socket.io> = 1.0 socket.io--phiên bày tỏ github.com/xpepermint/socket.io-express-session
blnc

4

Chỉnh sửa: Sau khi thử một số mô-đun không hoạt động, tôi đã thực sự đi và viết thư viện của riêng mình để làm điều này. Trình cắm không biết xấu hổ: hãy khám phá tại https://github.com/aviddiviner/Socket.IO-sessions . Tôi sẽ để lại bài đăng cũ của mình bên dưới cho các mục đích lịch sử:


Tôi đã làm việc này khá gọn gàng mà không cần phải bỏ qua các flashsocket vận chuyển theo pr0zac giải pháp của ở trên. Tôi cũng đang sử dụng express với Socket.IO. Đây là cách thực hiện.

Đầu tiên, chuyển ID phiên vào chế độ xem:

app.get('/', function(req,res){
  res.render('index.ejs', {
    locals: { 
      connect_sid: req.sessionID
      // ...
    }
  });
});

Sau đó, trong chế độ xem của bạn, hãy liên kết nó với phía máy khách Socket.IO:

<script>
  var sid = '<%= connect_sid %>';
  var socket = new io.Socket();
  socket.connect();
</script>
<input type="button" value="Ping" onclick="socket.send({sid:sid, msg:'ping'});"/>

Sau đó, trong trình nghe Socket.IO phía máy chủ của bạn, chọn nó và đọc / ghi dữ liệu phiên:

var socket = io.listen(app);
socket.on('connection', function(client){
  client.on('message', function(message){
    session_store.get(message.sid, function(error, session){
      session.pings = session.pings + 1 || 1;
      client.send("You have made " + session.pings + " pings.");
      session_store.set(message.sid, session);  // Save the session
    });
  });
});

Trong trường hợp của tôi, tôi session_storelà Redis, sử dụng redis-connectthư viện.

var RedisStore = require('connect-redis');
var session_store = new RedisStore;
// ...
app.use(express.session({ store: session_store }));

Hy vọng điều này sẽ giúp ai đó tìm thấy bài đăng này trong khi tìm kiếm trên Google (như tôi đã làm;)


8
Đặt id phiên của bạn trong html ứng dụng khách không phải là một ý tưởng hay từ góc độ bảo mật ...
UpTheCreek

4
Tại sao việc đặt id phiên trong HTML lại là một ý tưởng tồi khi ID phiên đã được lưu trữ trong một cookie cục bộ?
Gavin

3
Vì không thể truy cập cookie từ javascript khi được đặt làm cookie HttpOnly. Bằng cách đưa session.sid vào HTML, bạn cung cấp cho kẻ tấn công mọi thứ chúng cần trong DOM.
rochal

3

Xem cái này: Xác thực Socket.IO

Tôi khuyên bạn không nên tìm nạp bất kỳ thứ gì qua client.request...hoặc client.listener...vì thứ đó không được gắn trực tiếp vào clientđối tượng và luôn trỏ đến người dùng đăng nhập cuối cùng!


2

Kiểm tra Socket.IO-connect

Kết nối WebSocket Middleware Wrapper quanh Socket.IO-node https://github.com/bnoguchi/Socket.IO-connect

Điều này sẽ cho phép bạn đẩy (các) yêu cầu Socket.IO xuống ngăn xếp phần mềm trung gian Express / Connect trước khi xử lý nó với các trình xử lý sự kiện Socket.IO, cho phép bạn truy cập vào phiên, cookie và hơn thế nữa. Mặc dù, tôi không chắc rằng nó hoạt động với tất cả các phương tiện vận chuyển của Socket.IO.


thật không may, mô-đun đó vẫn đang sử dụng v0.6 của socket.io
fent

2

Bạn có thể sử dụng express-socket.io-session .

Chia sẻ phần mềm trung gian phiên nhanh dựa trên cookie với socket.io. Hoạt động với express> 4.0.0 và socket.io> 1.0.0 và sẽ không tương thích ngược.

Đã làm cho tôi!!


Chào. Bạn sẽ sử dụng các giá trị phiên trong giao diện người dùng như thế nào? Tôi không thể thấy chúng trong tài liệu npm.
Hari Ram

1

Bạn có thể xem tại đây: https://github.com/bmeck/session-web-sockets

hoặc bạn có thể sử dụng:

io.on('connection', function(client) { 
  var session = client.listener.server.viewHelpers; 
  // use session here 
});

Hi vọng điêu nay co ich.


Tôi biết session-web-socket nhưng tôi không muốn sử dụng thư viện cho việc này, tôi đang tìm một giải pháp đơn giản. Tôi đã thử client.listener.server.viewHelpers; nhưng nó trả về cái này: {}
sfs

2
mặc dù điều này thoạt đầu có vẻ hiệu quả, nhưng nó dẫn đến các điều kiện về chủng tộc. Tôi đề nghị bạn nên tránh nó hoàn toàn.
Shripad Krishna

1

Tôi không chắc rằng tôi đang làm đúng. https://github.com/LearnBoost/socket.io/wiki/Authorizing

Với dữ liệu bắt tay, bạn có thể truy cập vào cookie. Và trong cookie, bạn có thể lấy connect.sid là id phiên cho mỗi máy khách. Và sau đó sử dụng connect.sid để lấy dữ liệu phiên từ cơ sở dữ liệu (tôi giả sử bạn đang sử dụng RedisStore)


đây chính xác là con đường để đi nhưng của bạn không thú vị vì vậy bạn không thể nhận được điểm tràn ngăn xếp. github.com/tcr/socket.io-sessiongithub.com/osystemcallback/session.socket.io Tôi thích cái đầu tiên tốt hơn một chút là nó sạch hơn. Cái thứ hai được tài liệu tốt hơn một chút.
James

@TJ Tôi rất tiếc về điều đó nhưng bạn có nhận ra rằng câu trả lời là cách đây 2 năm không? Và có lẽ nó sẽ không hoạt động ngay bây giờ
Tan Nguyen

@TanNguyen Tôi biết, đó là lý do tại sao tôi thông báo cho bạn để bạn có thể cập nhật câu trả lời nhất thiết thay vì trỏ mọi người đến các liên kết chết
TJ

@TJ Cảm ơn bạn vì điều đó. Thật không may, tôi đã rời khỏi socket.io do vấn đề hiệu suất cách đây 2 năm. Do đó, tôi không biết cách xử lý hiện tại của session trong socket.io là gì
Tan Nguyen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.