Frage

Ich versuche, Socket.io in node.js zu verwenden, und versuche, dem Server jedem der Socket.io -Clients eine Identität zu geben. Da der Socket -Code außerhalb des Rahmens des HTTP -Servercodes liegt, hat er keinen einfachen Zugriff auf die gesendeten Anforderungsinformationen. Ich gehe davon aus, dass er während der Verbindung gesendet werden muss. Was ist der beste Weg dazu

1) Bringen Sie die Informationen an den Server darüber, wer über Socket.io herstellt.

2) Authentifizieren, wer sie sind (ich verwende gerade Express, wenn das die Dinge einfacher macht)

War es hilfreich?

Lösung

Verwenden Sie Connect-Redis und verfügen Sie über Redis als Session Store für alle authentifizierten Benutzer. Stellen Sie bei der Authentifizierung sicher, dass Sie den Schlüssel (normalerweise req.Sessionid) an den Client senden. Lassen Sie den Kunden diesen Schlüssel in einem Cookie speichern.

AUF SOCKET CONNECT (oder jederzeit später) diesen Schlüssel vom Cookie abrufen und an den Server zurücksenden. Abrufen Sie die Sitzungsinformationen in Redis mit diesem Schlüssel ab. (Get Schlüssel)

Z.B:

Serverseite (mit Redis als Sitzungsspeicher):

req.session.regenerate...
res.send({rediskey: req.sessionID});

Kundenseite:

//store the key in a cookie
SetCookie('rediskey', <%= rediskey %>); //http://msdn.microsoft.com/en-us/library/ms533693(v=vs.85).aspx

//then when socket is connected, fetch the rediskey from the document.cookie and send it back to server
var socket = new io.Socket();

socket.on('connect', function() {
  var rediskey = GetCookie('rediskey'); //http://msdn.microsoft.com/en-us/library/ms533693(v=vs.85).aspx
  socket.send({rediskey: rediskey});
});

Serverseite:

//in io.on('connection')
io.on('connection', function(client) {
  client.on('message', function(message) {

    if(message.rediskey) {
      //fetch session info from redis
      redisclient.get(message.rediskey, function(e, c) {
        client.user_logged_in = c.username;
      });
    }

  });
});

Andere Tipps

Mir hat auch den Weg gefallen Pusherapp tut private Kanäle.enter image description here

Eine eindeutige Socket -ID wird generiert und per Pusher an den Browser gesendet. Dies wird über eine AJAX -Anfrage an Ihre Anwendung (1) gesendet, die den Benutzer ermächtigt, auf den Kanal mit Ihrem vorhandenen Authentifizierungssystem zuzugreifen. Wenn Sie erfolgreich sind, gibt Ihre Bewerbung eine Autorisierungszeichenfolge an den Browser zurück, der mit Ihrem Pusher -Geheimnis signiert ist. Dies wird an Pusher über das Websocket gesendet, das die Autorisierung (2) abschließt, wenn die Autorisierungszeichenfolge übereinstimmt.

Weil auch socket.io hat eindeutig Socket_id für jeden Socket.

socket.on('connect', function() {
        console.log(socket.transport.sessionid);
});

Sie benutzten Unterzeichnete Autorisierungszeichenfolge Benutzer zu autorisieren.

Ich habe das noch nicht gespiegelt socket.io, aber ich denke, es könnte ein ziemlich interessantes Konzept sein.

Ich weiß, dass dies ein bisschen alt ist, aber für zukünftige Leser zusätzlich zum Ansatz des Analyse von Cookie und Abholung der Sitzung aus dem Speicher (zB. passport.Socketio ) Sie können auch einen tokenbasierten Ansatz in Betracht ziehen.

In diesem Beispiel verwende ich JSON -Web -Token, die ziemlich Standard sind. Sie müssen der Client -Seite das Token geben. In diesem Beispiel stellen Sie sich einen Authentifizierungsendpunkt vor, der JWT zurückgibt:

var jwt = require('jsonwebtoken');
// other requires

app.post('/login', function (req, res) {

  // TODO: validate the actual user user
  var profile = {
    first_name: 'John',
    last_name: 'Doe',
    email: 'john@doe.com',
    id: 123
  };

  // we are sending the profile in the token
  var token = jwt.sign(profile, jwtSecret, { expiresInMinutes: 60*5 });

  res.json({token: token});
});

Jetzt kann Ihr Socket.io -Server wie folgt konfiguriert werden:

var socketioJwt = require('socketio-jwt');

var sio = socketIo.listen(server);

sio.set('authorization', socketioJwt.authorize({
  secret: jwtSecret,
  handshake: true
}));

sio.sockets
  .on('connection', function (socket) {
     console.log(socket.handshake.decoded_token.email, 'has joined');
     //socket.on('event');
  });

Die Middleware von Socket.io-JWT erwartet das Token in einer Abfragezeichenfolge. Von dem Client müssen Sie es daher nur beim Anschließen anhängen:

var socket = io.connect('', {
  query: 'token=' + token
});

Ich habe eine detailliertere Erklärung zu dieser Methode und Cookies geschrieben hier.

Dieser Artikel (http://simplapi.wordpress.com/2012/04/13/php--node-js-session-share-redi/) zeigt, wie es geht

  • Speichern Sie die Sitzungen des HTTP -Servers in Redis (mit Predis)
  • Holen Sie sich diese Sitzungen von Redis in node.js durch die Sitzungs -ID in einem Cookie gesendet

Mit diesem Code können Sie sie auch in Socket.io erhalten.

var io = require('socket.io').listen(8081);
var cookie = require('cookie');
var redis = require('redis'), client = redis.createClient();
io.sockets.on('connection', function (socket) {
    var cookies = cookie.parse(socket.handshake.headers['cookie']);
    console.log(cookies.PHPSESSID);
    client.get('sessions/' + cookies.PHPSESSID, function(err, reply) {
        console.log(JSON.parse(reply));
    });
});

Hier ist mein Versuch, die folgenden Arbeiten zu haben:

  • ausdrücken: 4.14
  • Socket.io: 1.5
  • Reisepass (unter Verwendung von Sitzungen): 0,3
  • Redis: 2.6 (wirklich schnelle Datenstruktur für Sitzungen; Sie können aber auch andere wie MongoDB verwenden. Ich empfehle Ihnen jedoch, dies für Sitzungsdaten + MongoDB zu verwenden, um andere persistente Daten wie Benutzer zu speichern.

Da Sie vielleicht auch einige API -Anfragen hinzufügen möchten, werden wir auch verwenden http Paket, damit sowohl HTTP- als auch Web -Socket im selben Port arbeiten.


server.js

Der folgende Auszug enthält nur alles, was Sie benötigen, um die vorherigen Technologien einzustellen. Sie können die komplette Server.js -Version sehen, die ich in einem meiner Projekte verwendet habe hier.

import http from 'http';
import express from 'express';
import passport from 'passport';
import { createClient as createRedisClient } from 'redis';
import connectRedis from 'connect-redis';
import Socketio from 'socket.io';

// Your own socket handler file, it's optional. Explained below.
import socketConnectionHandler from './sockets'; 

// Configuration about your Redis session data structure.
const redisClient = createRedisClient();
const RedisStore = connectRedis(Session);
const dbSession = new RedisStore({
  client: redisClient,
  host: 'localhost',
  port: 27017,
  prefix: 'stackoverflow_',
  disableTTL: true
});

// Let's configure Express to use our Redis storage to handle
// sessions as well. You'll probably want Express to handle your 
// sessions as well and share the same storage as your socket.io 
// does (i.e. for handling AJAX logins).
const session = Session({
  resave: true,
  saveUninitialized: true,
  key: 'SID', // this will be used for the session cookie identifier
  secret: 'secret key',
  store: dbSession
});
app.use(session);

// Let's initialize passport by using their middlewares, which do 
//everything pretty much automatically. (you have to configure login
// / register strategies on your own though (see reference 1)
app.use(passport.initialize());
app.use(passport.session());

// Socket.IO
const io = Socketio(server);
io.use((socket, next) => {
  session(socket.handshake, {}, next);
});
io.on('connection', socketConnectionHandler); 
// socket.io is ready; remember that ^this^ variable is just the 
// name that we gave to our own socket.io handler file (explained 
// just after this).

// Start server. This will start both socket.io and our optional 
// AJAX API in the given port.
const port = 3000; // Move this onto an environment variable, 
                   // it'll look more professional.
server.listen(port);
console.info(`🌐  API listening on port ${port}`);
console.info(`🗲 Socket listening on port ${port}`);

Sockets/Index.js

Unser socketConnectionHandler, Ich mag es einfach nicht, alles in Server.js zu setzen (obwohl Sie es perfekt können), zumal diese Datei ziemlich schnell viel Code enthält.

export default function connectionHandler(socket) {
  const userId = socket.handshake.session.passport &&
                 socket.handshake.session.passport.user; 
  // If the user is not logged in, you might find ^this^ 
  // socket.handshake.session.passport variable undefined.

  // Give the user a warm welcome.
  console.info(`⚡︎ New connection: ${userId}`);
  socket.emit('Grettings', `Grettings ${userId}`);

  // Handle disconnection.
  socket.on('disconnect', () => {
    if (process.env.NODE_ENV !== 'production') {
      console.info(`⚡︎ Disconnection: ${userId}`);
    }
  });
}

Zusätzliches Material (Client):

Nur eine sehr grundlegende Version des JavaScript -Socket.io -Clients:

import io from 'socket.io-client';

const socketPath = '/socket.io'; // <- Default path.
                                 // But you could configure your server
                                // to something like /api/socket.io

const socket = io.connect('localhost:3000', { path: socketPath });
socket.on('connect', () => {
  console.info('Connected');
  socket.on('Grettings', (data) => {
    console.info(`Server gretting: ${data}`);
  });
});
socket.on('connect_error', (error) => {
  console.error(`Connection error: ${error}`);
});

Verweise:

Ich konnte einfach nicht im Code verweisen, also habe ich ihn hierher bewegt.

1: So richten Sie Ihre Passstrategien ein: https://scotch.io/tutorials/easy-node-authentication-setup--local#handling-signupregistration

Verwenden Sie Sitzung und Redis zwischen c/s

// Serverseite

io.use(function(socket, next) {
 console.log(socket.handshake.headers.cookie); // get here session id and match from redis session data
 next();
});

das sollte es tun

//server side

io.sockets.on('connection', function (con) {
  console.log(con.id)
})

//client side

var io = io.connect('http://...')

console.log(io.sessionid)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top