NodeJS - Socket.io 只允许经过 JWT 验证的连接

Posted

技术标签:

【中文标题】NodeJS - Socket.io 只允许经过 JWT 验证的连接【英文标题】:NodeJS - Socket.io allowing only JWT verified connections 【发布时间】:2015-07-20 05:23:04 【问题描述】:

我的代码就是这么简单:

/*global require module process console*/
/*eslint-disable*/
(function (require, process) 
  'use strict';

  var config = require('../config')
  , uuid = require('node-uuid')
  , crypto = require('crypto')
  , fs = require('fs')
  , port = parseInt(process.env.PORT || config.server.port, 10)
  , serverHandler = function (req, res) 
    res.writeHead(404);
    res.end();
  
  , httpUrl
  , io
  , server;

// Create an http(s) server instance to that socket.io can listen to
if (config.server.secure) 

  server = require('https').Server(
    'key': fs.readFileSync(config.server.key),
    'cert': fs.readFileSync(config.server.cert),
    'passphrase': config.server.password
  , serverHandler);
 else 

  server = require('http').Server(serverHandler);


server.listen(port);

io = require('socket.io').listen(server);

if (config.logLevel) 
    // https://github.com/Automattic/socket.io/wiki/Configuring-Socket.IO
    io.set('log level', config.logLevel);
  

  function describeRoom(name) 

    var clients = io.sockets.clients(name);

    var result = 
      'clients': 
    ;

    clients.forEach(function (client) 
      result.clients[client.id] = client.resources;
    );

    return result;
  

  function clientsInRoom(name) 

    return io.sockets.clients(name).length;
  

  function safeCb(cb) 

    if (typeof cb === 'function') 
      return cb;
    
  

  io.sockets.on('connection', function (client) 

    client.resources = 
      'screen': false,
      'video': true,
      'audio': false
    ;

    // pass a message to another id
    client.on('message', function (details) 

      if (!details) 

        return;
      

      var otherClient = io.sockets.sockets[details.to];

      if (!otherClient) 

        return;
      

      details.from = client.id;
      otherClient.emit('message', details);
    );

    client.on('shareScreen', function () 

      client.resources.screen = true;
    );

    client.on('unshareScreen', function (type) 

      client.resources.screen = false;
      removeFeed('screen');
    );

    client.on('join', join);

    function removeFeed(type) 
      if (client.room) 

        io.sockets.in(client.room).emit('remove', 
          'id': client.id,
          'type': type
        );

        if (!type) 

          client.leave(client.room);
          client.room = undefined;
        
      
    

    function join(name, cb) 
        // sanity check
        if (typeof name !== 'string') 

          return;
        
        // check if maximum number of clients reached
        if (config.rooms
          && config.rooms.maxClients > 0
          && clientsInRoom(name) >= config.rooms.maxClients) 

          safeCb(cb)('full');
        return;
      
        // leave any existing rooms
        removeFeed();
        safeCb(cb)(null, describeRoom(name));
        client.join(name);
        client.room = name;
      

    // we don't want to pass 'leave' directly because the
    // event type string of 'socket end' gets passed too.
    client.on('disconnect', function () 
      removeFeed();
    );
    client.on('leave', function () 
      removeFeed();
    );

    client.on('create', function (name, cb) 
      if (arguments.length == 2) 
        cb = (typeof cb == 'function') ? cb : function () ;
        name = name || uuid();
       else 
        cb = name;
        name = uuid();
      
        // check if exists
        if (io.sockets.clients(name).length) 
          safeCb(cb)('taken');
         else 
          join(name);
          safeCb(cb)(null, name);
        
      );

    // support for logging full webrtc traces to stdout
    // useful for large-scale error monitoring
    client.on('trace', function (data) 
      console.log('trace', JSON.stringify(
        [data.type, data.session, data.prefix, data.peer, data.time, data.value]
        ));
    );


    // tell client about stun and turn servers and generate nonces
    client.emit('stunservers', config.stunservers || []);

    // create shared secret nonces for TURN authentication
    // the process is described in draft-uberti-behave-turn-rest
    var credentials = [];

    config.turnservers.forEach(function (server) 

      var hmac = crypto.createHmac('sha1', server.secret);
        // default to 86400 seconds timeout unless specified
        var username = Math.floor(new Date().getTime() / 1000) + (server.expiry || 86400) + '';

        hmac.update(username);

        credentials.push(
          'username':username,
          'credential':hmac.digest('base64'),
          'url':server.url
        );
      );
    client.emit('turnservers', credentials);
  );

if (config.uid) 

  process.setuid(config.uid);


if (config.server.secure) 

  httpUrl = 'https://localhost:' + port;
 else 

  httpUrl = 'http://localhost:' + port;


console.info('Signaling WS is running at:' + httpUrl);
/*eslint-enable*/
(require, process));

我只想在 socket.io 上只允许经过 jwt 验证的连接,我该怎么做?

实际上我会阻止任何未经 jwt 身份验证的用户连接到 socket.io...

用户通过 express-jwt expressJWT.sign(userProfile, config.secretKey) 方法签名

任何帮助表示感谢!

【问题讨论】:

【参考方案1】:

解决了

socketioJwt = require('socketio-jwt');

io.set('authorization', socketioJwt.authorize(
    secret: secretKey,
    handshake: true
  ));

【讨论】:

以上是关于NodeJS - Socket.io 只允许经过 JWT 验证的连接的主要内容,如果未能解决你的问题,请参考以下文章

如何允许其他网络连接到服务器 nodejs socket io

NodeJs Socket.io 房间

验证 socket.io/nodejs 的用户

NodeJs - express 和 socket.io 同端口集成

如何使用socket.io mysql nodejs express删除帖子

部署后 Socket.io 不工作 - 抛出错误 - 405(不允许)