基于JWT的Socket.io用户认证

转载请注明出处:
http://blog.csdn.net/Soaring_Tiger/article/details/51439605

翻译自 Token-based Authentication with Socket.IO 原文标题及内容略有删改

在实时框架里进行用户认证(Authentication)是非常有挑战的一件事,因为实时系统与常规的web app是有很大差别的。其风险在于如果没有准确的进行用户认证,那么你很可能就会把数据流发送到错误的用户那里去。因为socket系统不能自动的知道谁是登录用户,因此理论上任何人都可以加入到数据流当中。

图1.很多人会误用的Socket.IO认证方式
基于JWT的Socket.io用户认证_第1张图片

很多人错误的认为:只要用户在页面上登录了一次,那么就可以自动的在socket stream数据流中得到认证。实际上这是两个完全不同的通道(channels)。

有两种思路可以解决上述问题,一种是传统的基于cookie的认证方式,还有一种是基于JWT(JSON Web Tokens)的认证方式,下图是两种方式的比较:
基于JWT的Socket.io用户认证_第2张图片图2

对于两种方法的比较,我们另文再讨论,现在就介绍一下基于JWT的认证实现。

基于JWT的Socket.IO认证

服务端端的实现

var jwt = require('jsonwebtoken');
// 其它的库此处略掉...

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

  // TODO: 验证实际用户
  var profile = {
    first_name: 'John',
    last_name: 'Doe',
    email: '[email protected]',
    id: 123
  };

  // 将用户信息加密在令牌内
  var token = jwt.sign(profile, jwtSecret, { expiresInMinutes: 60*5 });

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

var server = http.createServer(app);

然后是socket.io的相关代码:

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

var sio = socketIo.listen(server);

sio.set('authorization', socketioJwt.authorize({
  secret: jwtSecret,
  handshake: true
}));
//上述JWT用密钥 jwtSecret 签名加密。
sio.sockets
  .on('connection', function (socket) {
     console.log(socket.handshake.decoded_token.email, 'connected');
     //socket.on('event');
  });

server.listen(9000, function () {
  console.log('listening on http://localhost:9000');
});

在与socket.io客户端握手的时候,要求验证JWT,如果JWT是正确的,那么连接(connection)事件就被触发了。

客户端的实现

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

  socket.on('connect', function () {
    console.log('authenticated');
  }).on('disconnect', function () {
    console.log('disconnected');
  });
}

$('#login').submit(function (e) {
  e.preventDefault();
  $.post('/login', {
    username: $('username').val(),
    password: $('password').val()
  }).done(function (result) {
    connect_socket(result.token);
  });
});

完整实现的代码见Git

你可能感兴趣的:(NodeJS,Socket-IO)