验证套接字io连接

el_*_*_le 66 token node.js flask socket.io

如何验证socket.io连接?我的应用程序使用来自另一台服务器(python)的登录端点来获取令牌,每当用户在节点端打开套接字连接时,我如何才能使用该令牌?

io.on('connection', function(socket) {
    socket.on('message', function(message) {
        io.emit('message', message);
    });
});
Run Code Online (Sandbox Code Playgroud)

而客户方:

var token = sessionStorage.token;
var socket = io.connect('http://localhost:3000', {
    query: 'token=' + token
});
Run Code Online (Sandbox Code Playgroud)

如果令牌是在python中创建的:

token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')
Run Code Online (Sandbox Code Playgroud)

如何使用此令牌验证节点中的套接字连接?

has*_*sin 148

令牌是否在另一台服务器上创建并不重要.如果您有正确的密钥和算法,您仍然可以验证它.

jsonwebtoken模块实现

客户

var token = sessionStorage.token;
var socket = io.connect('http://localhost:3000', {
  query: {token: token}
});
Run Code Online (Sandbox Code Playgroud)

服务器

var io = require('socket.io')();
var jwt = require('jsonwebtoken');

io.use(function(socket, next){
  if (socket.handshake.query && socket.handshake.query.token){
    jwt.verify(socket.handshake.query.token, 'SECRET_KEY', function(err, decoded) {
      if(err) return next(new Error('Authentication error'));
      socket.decoded = decoded;
      next();
    });
  } else {
      next(new Error('Authentication error'));
  }    
})
.on('connection', function(socket) {
    // Connection now authenticated to receive further events

    socket.on('message', function(message) {
        io.emit('message', message);
    });
});
Run Code Online (Sandbox Code Playgroud)

socketio-jwt模块实现

此模块使客户端和服务器端的身份验证变得更加容易.看看他们的例子吧.

客户

var token = sessionStorage.token;
var socket = io.connect('http://localhost:3000');
socket.on('connect', function (socket) {
  socket
    .on('authenticated', function () {
      //do other things
    })
    .emit('authenticate', {token: token}); //send the jwt
});
Run Code Online (Sandbox Code Playgroud)

服务器

var io = require('socket.io')();
var socketioJwt = require('socketio-jwt');

io.sockets
  .on('connection', socketioJwt.authorize({
    secret: 'SECRET_KEY',
    timeout: 15000 // 15 seconds to send the authentication message
  })).on('authenticated', function(socket) {
    //this socket is authenticated, we are good to handle more events from it.
    console.log('hello! ' + socket.decoded_token.name);
  });
Run Code Online (Sandbox Code Playgroud)

  • 你好,我需要问,连接或每次发射事件都需要令牌一次吗? (4认同)
  • 不完全相关,但是您从存储在 sessionStorage.token 中的端点收到的令牌?这意味着您页面上运行的任何 JS 都可以访问该令牌,对吧?是什么阻止外部 JS 代码(如 Chrome 扩展)读取令牌并使用它登录自己的套接字,就好像他们是您一样?这就像一个带有 HttpOnly:false 的 cookie 来存储您的访问权限。我还尝试通过来自外部服务器的令牌来识别套接字连接,但我还没有找到一种方法来在令牌到达客户端后对其进行保密,因为任何(其他外部)JS 也可以读取它。:( 有任何想法吗? (4认同)
  • 对于任何获得“无法读取未定义属性”的人;只需从 `function(socket)` 中删除 `socket`。 (4认同)
  • 将敏感数据添加到 URL 是一种不好的做法。您可以阅读这篇文章以了解不同的方法。https://facundoolano.wordpress.com/2014/10/11/better-authentication-for-socket-io-no-query-strings/ (4认同)
  • 如果用户最初未经授权并且在第一次尝试时没有秘密,您将如何重新连接到服务器? (3认同)

小智 8

由于我没有足够的声誉来添加评论到接受的答案:

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

实际上并不属于 auth0 的存储库,而是基于第三方社区的软件包。

上面的答案应该更新,因为 auth0 存储库的链接是第 404 页。


Muh*_*fay 6

在这里我写了一篇关于如何在套接字上对用户进行身份验证并保存用户数据的深入文章

https://medium.com/@tameemrafay/how-to-authenticate-user-and-store-the-data-in-sockets-19b262496feb

客户端代码

import io from "socket.io-client";

const SERVER = "localhost:4000";
const socket = io(SERVER, {
    auth: {
      token: "2c87b3d5412551ad69aet757f81f6a73eb919e5b02467aed419f5b2a9cce2b5aZOzgaM+bpKfjdM9jvez37RTEemAp07kOvEFJ3pBzvj8="
    }
  });

 socket.once('connect', (socketConnection) => {
    console.log('socket connected', socketConnection);
  })
 
// Emit the message and receive data from server in callback
 socket.emit("user send message", {message: "Hi you there" }, callback => {
    if (callback) {
      console.log("--- response from server", callback);
     }
  });
Run Code Online (Sandbox Code Playgroud)

服务器端代码

const initializeSockets = (io) => {
  io.on('connection', (socket) => {

  decryptAndStoreUserData(socket,io);
  
}

const decryptAndStoreUserData = async (socket,io) => {

    const { token } = socket.handshake.auth; // receive the token from client

    // here i decypt the auth token and get the user data
    const genToken = new Middlewares().token();
    const userData = genToken.decryptTokenForSockets(token);

    // save the data of user in socket
    socket.data.user = userData;

  }
Run Code Online (Sandbox Code Playgroud)


Yil*_*maz 6

写一个中间件:

const jwt = require("jsonwebtoken");

const authSocketMiddleware = (socket, next) => {
  // since you are sending the token with the query
  const token = socket.handshake.query?.token;
  try {
    const decoded = jwt.verify(token, process.env.TOKEN_SECRET_KEY);
    socket.user = decoded;
  } catch (err) {
    return next(new Error("NOT AUTHORIZED"));
  }
  next();
};

module.exports = authSocketMiddleware;
Run Code Online (Sandbox Code Playgroud)

在套接字服务器内部使用它

socketServer = (server) => {
  const io = require("socket.io")(server, {
    cors: {
      origin: "*",
      methods: ["GET", "POST"],
    },
  });
  // before connection use the middleware
  io.use((socket, next) => {
    authSocketMiddleware(socket, next);
  });
  io.on("connection", (socket) => {
    console.log("user connected", socket.id);
  });
};
Run Code Online (Sandbox Code Playgroud)