133 votes

Authentification Socket.IO

J'essaie d'utiliser Socket.IO dans Node.js, et je tente de permettre au serveur de donner une identité à chacun des clients Socket.IO. Comme le code du socket est en dehors de la portée du code du serveur http, il n'a pas facilement accès aux informations de la requête envoyée, donc je suppose qu'elles devront être envoyées pendant la connexion. Quelle est la meilleure façon de

1) obtenir l'information au serveur sur qui se connecte via Socket.IO

2) authentifier qui ils disent être (j'utilise actuellement Express, si cela facilite les choses).

107voto

Shripad K Points 6594

Utilisez connect-redis et faites de redis votre magasin de session pour tous les utilisateurs authentifiés. Assurez-vous qu'à l'authentification vous envoyez la clé (normalement req.sessionID) au client. Demandez au client de stocker cette clé dans un cookie.

Lors de la connexion du socket (ou à tout moment par la suite), récupérez cette clé dans le cookie et renvoyez-la au serveur. Récupérer les informations de session dans redis en utilisant cette clé. (GET key)

Eg :

Côté serveur (avec redis comme magasin de session) :

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

Côté client :

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

Côté serveur :

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

  });
});

3 votes

Il y a un nouveau lien intéressant à ce sujet => danielbaulig.de/socket-ioexpress

1 votes

Aha ! Ce lien est vraiment bon. Ceci est dépassé (utilise Socket.IO 0.6.3) ! Essentiellement le même concept. Récupérer le cookie, vérifier dans le magasin de session et s'authentifier :)

0 votes

@NightWolf cela devrait fonctionner car vous récupérez le cookie en javascript et non en flash (actionscript). GetCookie est une fonction javascript.

33voto

Alfred Points 32190

J'ai aussi aimé la façon dont pusherapp fait chaînes privées . enter image description here

Un identifiant de socket unique est généré et envoyé au navigateur par Pusher. Celui-ci est envoyé à votre application (1) via une requête AJAX qui autorise l'utilisateur à accéder au canal en utilisant votre système d'authentification existant. Si succès, votre application renvoie une chaîne d'autorisation au navigateur signée avec votre secret Pusher. Cette chaîne est envoyée à Pusher via le WebSocket, qui complète l'autorisation (2) si la chaîne d'autorisation correspond.

Parce que aussi socket.io a un socket_id unique pour chaque socket.

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

Ils ont utilisé chaînes d'autorisation signées pour autoriser les utilisateurs.

Je n'ai pas encore fait de copie de ceci à socket.io mais je pense que ce concept pourrait être intéressant.

3 votes

C'est génial. Mais il serait plus facile d'utiliser les cookies si votre serveur d'applications et votre serveur websocket ne sont pas séparés. Mais vous souhaitez généralement séparer les deux (il sera plus facile de faire évoluer le serveur de socket s'il est séparé). Donc c'est bon :)

1 votes

@Shripad vous avez tout à fait raison et j'aime aussi beaucoup votre mise en œuvre :P

33voto

Je sais que c'est un peu vieux, mais pour les futurs lecteurs, en plus de l'approche consistant à analyser les cookies et à récupérer la session à partir du stockage (ex. passeport.socketio ), vous pouvez également envisager une approche basée sur les jetons.

Dans cet exemple, j'utilise des jetons Web JSON qui sont assez standard. Vous devez donner le jeton à la page client, dans cet exemple imaginez un endpoint d'authentification qui renvoie JWT :

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

Maintenant, votre serveur socket.io peut être configuré comme suit :

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

L'intergiciel socket.io-jwt s'attend à ce que le jeton soit inclus dans une chaîne de requête, de sorte que le client n'a qu'à le joindre au moment de la connexion :

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

J'ai écrit une explication plus détaillée sur cette méthode et les cookies. aquí .

0 votes

Petite question, pourquoi envoyez-vous le profil avec le jeton s'il ne peut pas être décodé sur le client ?

0 votes

C'est possible. JWT est juste une signature numérique en base64. Le client peut le décoder, mais il ne peut pas valider la signature dans cet exemple.

0 votes

@JoséF.Romaniello votre article est en panne, j'aime bien votre approche cependant.

2voto

Blade1336 Points 21

Cet article ( http://simplapi.wordpress.com/2012/04/13/php-and-node-js-session-share-redi/ ) montre comment

  • stocker les sessions du serveur HTTP dans Redis (en utilisant Predis)
  • récupérer ces sessions de Redis dans node.js par l'identifiant de session envoyé dans un cookie

En utilisant ce code, vous êtes en mesure de les obtenir dans socket.io, aussi.

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

-6voto

dominic Points 329

Cela devrait le faire

//server side

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

//client side

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

console.log(io.sessionid)

1 votes

Io.socket.sessionid dans mon cas

9 votes

Ce n'est même pas une tentative de réponse. Ce n'est pas de l'authentification, c'est simplement établir une connexion.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X