socket.io และ session?


96

ฉันใช้เฟรมเวิร์กด่วน ฉันต้องการเข้าถึงข้อมูลเซสชันจาก socket.io ฉันลองใช้ dynamicHelpers ด่วนกับข้อมูล client.listener.server.dynamicViewHelpers แต่ไม่สามารถรับข้อมูลเซสชันได้ มีวิธีง่ายๆในการทำเช่นนี้หรือไม่? โปรดดูรหัส

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
หรืออาจใช้โพสต์ VERY NICE นี้: danielbaulig.de/socket-ioexpress
Fabiano Soriani

3
@FabianoPS - จะไม่ทำงานอีกต่อไป - การเชื่อมต่อไม่ได้ให้เมธอด parseCookie ที่ใช้สิ่งนี้อีกต่อไป
UpTheCreek

1
@UpTheCreek - เนื่องจากการเชื่อมต่อไม่ได้ใช้เมธอด parseCookie อีกต่อไปสิ่งนี้จะเป็นไปได้อย่างไร?
ออสเตรีย

@Aust - คำถามดีฉันไม่รู้ว่าตอนนี้แนวทางที่ดีที่สุดคืออะไร นี่เป็น IMO ที่ยุ่งเหยิงจริงๆ การอภิปรายวิธีแก้ปัญหาส่วนใหญ่ที่น่ารำคาญนั้นเน้นที่ socket.io ด้วย (ไม่ใช่ทุกคนที่ใช้ socket.io!) ตอนนี้มีฟังก์ชัน parseSignedCookie แต่ก็เป็นแบบส่วนตัวเช่นกันดังนั้นจึงเสี่ยงต่อการทำลายการเปลี่ยนแปลงด้วย
UpTheCreek

2
สำหรับเวอร์ชันใหม่กว่าของ Socket.IO (1.x) และ Express (4.x) ตรวจสอบคำถาม SO นี้: stackoverflow.com/questions/25532692/…
tkit

คำตอบ:


68

วิธีนี้ใช้ไม่ได้กับซ็อกเก็ตที่อยู่เหนือการขนส่งแฟลชซ็อกเก็ต (ไม่ได้ส่งคุกกี้ที่จำเป็นไปยังเซิร์ฟเวอร์) แต่ทำงานได้อย่างน่าเชื่อถือ ฉันเพิ่งปิดใช้งานการขนส่ง flashsocket ในรหัสของฉัน

เพื่อให้ใช้งานได้ในด้าน express / connect ฉันกำหนดที่เก็บเซสชันอย่างชัดเจนเพื่อให้สามารถใช้งานได้ภายในซ็อกเก็ต:

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

จากนั้นภายในรหัสซ็อกเก็ตของฉันฉันรวมกรอบการเชื่อมต่อเพื่อให้ฉันสามารถใช้การแยกวิเคราะห์คุกกี้เพื่อดึงการเชื่อมต่อ sid จากคุกกี้ จากนั้นฉันค้นหาเซสชันในที่เก็บเซสชันที่มีการเชื่อมต่อนั้น:

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

จากนั้นคุณสามารถใช้เซสชันได้ตามต้องการ


3
ดูเหมือนว่า socket_client.request ถูกลบออกในเวอร์ชันล่าสุดของ socket.io-node
ศิลปะ

6
ระวัง ... มีอนุสัญญาใหม่สำหรับการดำเนินการนี้ ... ฉันขอแนะนำให้ใช้การตรวจสอบความถูกต้อง Socket.IO แทน ดูโพสต์จาก @Jeffer
BMiner

2
น่าเสียดายที่สิ่งนี้จะใช้ไม่ได้อีกต่อไป parseCookie ไม่ได้เป็นส่วนหนึ่งของเครื่องมือเชื่อมต่ออีกต่อไป เห็นได้ชัดว่ามันไม่เคยเป็นส่วนหนึ่งของ API สาธารณะ มีทางเลือกอื่นที่ยุ่งยาก - parseSignedCookie แต่นี่ก็เป็นแบบส่วนตัวด้วยดังนั้นฉันเดาว่ามันเสี่ยงที่จะหายไปเหมือนกัน ..
UpTheCreek

ตอนนี้ฉันกำลังคิดเกี่ยวกับเรื่องนี้ .... ทำไมไม่เพียงแค่ตั้งร้านสำหรับคุกกี้และร้านสำหรับซ็อกเก็ตเป็นร้านเดียวกัน?
James

34

โซลูชันโมดูลเซสชัน Socket.IO ทำให้แอปถูกโจมตี XSS โดยการเปิดเผยรหัสเซสชันที่ระดับไคลเอนต์ (สคริปต์)

ตรวจสอบโซลูชันนี้แทน (สำหรับ Socket.IO> = v0.7) ดูเอกสารที่นี่


1
@Jeffer - โซลูชันที่สองจะไม่ทำงานอีกต่อไปกับการเชื่อมต่อเวอร์ชันปัจจุบัน
UpTheCreek

2
-1 socket.ioคือสิ่งที่เปิดเผยรหัสเซสชันไม่ใช่โมดูลนั้น นี่ไม่ใช่เรื่องใหญ่เนื่องจากรหัสเซสชันจะถูกเก็บไว้ในฝั่งไคลเอ็นต์ในคุกกี้อย่างไรก็ตามบทช่วยสอนนั้นใช้ไม่ได้กับ Express เวอร์ชันล่าสุด
ออสเตรีย

1
ลิงค์โซลูชันของคุณเพียงแค่เปลี่ยนเส้นทางไปยังsocket.ioหน้า github .. ?
TJ

8

ฉันไม่แนะนำให้สร้างล้อใหม่ทั้งหมด เครื่องมือที่คุณต้องการเป็นแพ็คเกจ npm อยู่แล้วฉันคิดว่านี่คือสิ่งที่คุณต้องการ: session.socket.io ฉันใช้มันในวันนี้และจะเป็นประโยชน์มากฉันเดา !! การเชื่อมโยงเซสชันด่วนเข้ากับเลเยอร์ socket.io จะมีข้อดีมากมาย!


6
นี่คือโมดูลที่อัปเดตซึ่งรองรับ socket.io-express-sessions สำหรับ socket.io> = 1.0 github.com/xpepermint/socket.io-express-session
blnc

4

แก้ไข:หลังจากลองใช้โมดูลบางตัวที่ใช้งานไม่ได้ฉันได้ไปและเขียนไลบรารีของตัวเองเพื่อทำสิ่งนี้ เสียบด้านหน้า: ไปตรวจสอบออกที่https://github.com/aviddiviner/Socket.IO-sessions ฉันจะทิ้งโพสต์เก่าไว้ด้านล่างเพื่อวัตถุประสงค์ทางประวัติศาสตร์:


ผมได้งานนี้ค่อนข้างเรียบร้อยโดยไม่ต้องบายพาสflashsocketขนส่งตามpr0zac 's วิธีการแก้ปัญหาดังกล่าวข้างต้น ฉันยังใช้ Express กับ Socket.IO นี่คือวิธีการ

ขั้นแรกส่งรหัสเซสชันไปยังมุมมอง:

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

จากนั้นในมุมมองของคุณให้เชื่อมโยงกับฝั่งไคลเอ็นต์ 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'});"/>

จากนั้นในผู้ฟัง Socket.IO ฝั่งเซิร์ฟเวอร์ของคุณให้หยิบและอ่าน / เขียนข้อมูลเซสชัน:

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

ในกรณีของฉันฉันsession_storeคือ Redis โดยใช้redis-connectห้องสมุด

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

หวังว่านี่จะช่วยคนที่พบโพสต์นี้ขณะค้นหา Google (เหมือนที่เคยทำ;)


8
การใส่รหัสเซสชันของคุณใน html ไคลเอนต์ไม่ใช่ความคิดที่ดีจากมุมมองด้านความปลอดภัย ...
UpTheCreek

4
เหตุใดการใส่รหัสเซสชันใน HTML จึงเป็นความคิดที่ไม่ดีเมื่อรหัสเซสชันถูกเก็บไว้ในคุกกี้ภายใน
Gavin

3
เนื่องจากไม่สามารถเข้าถึงคุกกี้จากจาวาสคริปต์เมื่อตั้งค่าเป็นคุกกี้ HttpOnly การใส่ session.sid ใน HTML จะทำให้ผู้โจมตีได้รับทุกสิ่งที่พวกเขาต้องการใน DOM
rochal

3

ดูสิ่งนี้: การพิสูจน์ตัวตน Socket.IO

ฉันขอแนะนำว่าอย่าดึงสิ่งใด ๆ ผ่านclient.request...หรือclient.listener...เนื่องจากไม่ได้แนบโดยตรงกับclientวัตถุและชี้ไปที่ผู้ใช้ที่เข้าสู่ระบบคนสุดท้ายเสมอ!


2

ตรวจสอบSocket.IO-connect

เชื่อมต่อ WebSocket Middleware Wrapper รอบ ๆ Socket.IO-node https://github.com/bnoguchi/Socket.IO-connect

สิ่งนี้จะช่วยให้คุณสามารถผลักคำขอ Socket.IO ลงในสแต็กมิดเดิลแวร์ Express / Connect ก่อนที่จะจัดการกับตัวจัดการเหตุการณ์ Socket.IO ทำให้คุณสามารถเข้าถึงเซสชันคุกกี้และอื่น ๆ ได้ แม้ว่าฉันไม่แน่ใจว่ามันใช้ได้กับการขนส่งทั้งหมดของ Socket.IO


น่าเสียดายที่โมดูลยังคงใช้ v0.6 ของ socket.io
fent

2

คุณสามารถทำให้การใช้งานด่วน socket.io เซสชั่น

แชร์มิดเดิลแวร์ของเซสชันด่วนที่อิงคุกกี้กับ socket.io ทำงานร่วมกับ express> 4.0.0 และ socket.io> 1.0.0 และจะไม่เข้ากันได้แบบย้อนหลัง

ทำงานให้ฉัน !!


เฮ้. คุณจะใช้ค่าเซสชันในส่วนหน้าอย่างไร ฉันไม่เห็นพวกเขาในเอกสาร npm
Hari Ram

1

คุณสามารถดูได้ที่: https://github.com/bmeck/session-web-sockets

หรือคุณสามารถใช้:

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

หวังว่านี่จะช่วยได้


ฉันรู้จัก session-web-sockets แต่ฉันไม่ต้องการใช้ไลบรารีสำหรับสิ่งนี้ฉันกำลังมองหาวิธีง่ายๆ ฉันลอง client.listener.server.viewHelpers; แต่ส่งกลับสิ่งนี้: {}
sfs

2
แม้ว่าสิ่งนี้จะได้ผลในตอนแรก แต่ก็นำไปสู่สภาพการแข่งขัน ฉันขอแนะนำให้คุณหลีกเลี่ยงโดยสิ้นเชิง
ศรีปทุมกฤษณะ

1

ฉันไม่แน่ใจว่าฉันทำถูกต้อง https://github.com/LearnBoost/socket.io/wiki/Authorizing

ด้วยข้อมูลการจับมือคุณสามารถเข้าถึงคุกกี้ได้ และในคุกกี้คุณสามารถคว้า connect.sid ซึ่งเป็นรหัสเซสชันสำหรับไคลเอนต์แต่ละราย จากนั้นใช้ connect.sid เพื่อรับข้อมูลเซสชันจากฐานข้อมูล (ฉันสมมติว่าคุณใช้ RedisStore)


นี่เป็นวิธีที่จะไป แต่คุณไม่เจ๋งดังนั้นคุณจึงไม่สามารถรับคะแนนสแต็กล้นได้ github.com/tcr/socket.io-sessionและgithub.com/functioncallback/session.socket.ioฉันชอบตัวแรกดีกว่าเล็กน้อยสะอาดกว่า อันที่สองเป็นเอกสารที่ดีกว่าเล็กน้อย
James

@TJ ฉันเสียใจกับเรื่องนั้น แต่คุณรู้ไหมว่าคำตอบคือ 2 ปีที่แล้ว? และตอนนี้คงใช้ไม่ได้แล้ว
Tan Nguyen

@TanNguyen ฉันรู้นั่นคือเหตุผลที่ฉันแจ้งให้คุณทราบเพื่อให้คุณสามารถอัปเดตคำตอบได้ดีกว่าการชี้ให้คนอื่นไปที่ลิงก์ที่ตายแล้ว
TJ

@TJ ขอบคุณสำหรับสิ่งนั้น น่าเสียดายที่ฉันย้ายออกจาก socket.io เนื่องจากปัญหาด้านประสิทธิภาพเมื่อ 2 ปีก่อน ดังนั้นฉันไม่รู้ว่าวิธีการจัดการกับเซสชันใน socket.io ในปัจจุบันเป็นอย่างไร
Tan Nguyen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.