Socket.io-client: Permitir que socket.handshake.query sea una función

Creado en 22 may. 2017  ·  9Comentarios  ·  Fuente: socketio/socket.io-client

Tú quieres:

  • [x] informar un error
  • [] solicitar una función

Comportamiento actual

socket.handshake.query actualmente permite que los datos se establezcan en connect , pero no se pueden actualizar por referencia antes de que se active reconnect . Esto causa problemas al autorizar una conexión de socket con tokens de actualización.

Pasos para reproducir (si el comportamiento actual es un error)

//client
io.connect("wss://socket.server.com", {
   query : {
      token:"something dynamic"
   }
});

Si el servidor se reinicia y los clientes reconnect , el token puede estar desactualizado al volver a autorizar el socket.

//server
io.use(function(socket, next) {
   var query = socket.handshake.query;
   if(isValidToken(query.token)){
      next();//will never fire if the token has been updated
   }
});

Comportamiento esperado

Permitir que la consulta sea function :

io.connect("wss://socket.server.com", {
   query : function(){
      return {
         token:"something dynamic"
      }
   }
});

Configuración

  • versión de socket.io: 2.0.1

Como arreglar

En el constructor de Socket actual:

if (opts && opts.query) {
   this.query = opts.query;
}

Se puede cambiar a esto:

if(opts && opts.query) {
   this.query = typeof opts.query == 'function' && opts.query.call(this) || opts.query;
}

Comentario más útil

Actualmente @reeltimedoktor usted debe ser capaz de actualizar el query objeto en reconnect_attempt evento:

socket.on('reconnect_attempt', function () {
  socket.io.opts.query = { token: /* ... */ };
});

Todos 9 comentarios

+1
La corrección para el error # 1086 también debería resolver su problema. Cambiar las opciones de consulta después de una conexión exitosa funcionaba con la versión anterior de socket.io-client, pero con la versión actual, la referencia al objeto de consulta se pierde :(

Actualmente @reeltimedoktor usted debe ser capaz de actualizar el query objeto en reconnect_attempt evento:

socket.on('reconnect_attempt', function () {
  socket.io.opts.query = { token: /* ... */ };
});

La solución de @darrachequesne no parece funcionar para mí :(

Estoy en socket.io-client versión 2.3.0 en el cliente, con un servidor de nodo con socket.io versión 2.3.0 .

En el cliente estoy haciendo esto:

 socket.on('reconnect_attempt', async () => {
      const newToken = await getNewToken();
      socket.io.opts.query = {
        token: latestToken,
      };
    });

Y luego el servidor está autenticando el token usando un middleware pasado a io.use() (que debería dispararse cuando el socket se conecta o se vuelve a conectar, ¿afaik?).

En el momento en que la autenticación del servidor falla al reconectarse, dice que el token ha expirado, parece que el nuevo token no está siendo asignado correctamente a socket.io.opts.query.token . ¿Alguna idea de por qué?

Gracias :)

Actualización: Parece que hay un montón de lugares diferentes en el objeto socket donde se almacena el token de autenticación, por ejemplo, socket.io.engine.query.token , socket.io.engine.transport.query.token . Estos no se completan automáticamente cuando configura socket.io.opts.query.token . Sin embargo, cambiarlos todavía no afecta lo que los servidores 'ven'; todavía solo ve el token antiguo.

El token también parece estar incluido como un parámetro de URL en algunos de los campos de URL en el objeto de socket. ¿Quizás estos también deban actualizarse?

Después de investigar más a fondo, parece que configurar el token en socket.io.opts.query.token es suficiente para cambiar el token para la reautenticación al volver a conectar; algo más parece ser el problema para mi aplicación, tal vez algo que ver con la generación de token de autenticación de base de fuego. Entonces, para cualquier otra persona que se encuentre con esto, ¡la solución de @darrachequesne funciona!

Ok, creo que lo he solucionado; debes asegurarte de que estás obteniendo el nuevo token sincrónicamente en la devolución de llamada 'reconnect_attempt', es decir, no hagas esto:

 socket.on('reconnect_attempt', async () => {
      const newToken = await getNewToken(); // won't work
      socket.io.opts.query = {
        token: latestToken,
      };
    });

Parece que la autenticación del lado del servidor se estaba realizando antes de que se estableciera el nuevo token. Si obtiene el token sincrónicamente (obteniéndolo algún tiempo antes y almacenándolo, y luego recuperándolo en la devolución de llamada del oyente), el servidor obtiene el nuevo token de autenticación a tiempo para la autenticación de reconexión.

con "socket.io-client": "3.0.4" obtengo TS2341: Property 'opts' is private and only accessible within class 'Manager'. error. Estoy usando "typescript": "4.1.3"
image

Ok, creo que lo he solucionado, debes asegurarte de que estás obteniendo el nuevo token _sincrónicamente_ en la devolución de llamada 'reconnect_attempt', es decir, no hagas esto:

 socket.on('reconnect_attempt', async () => {
      const newToken = await getNewToken(); // won't work
      socket.io.opts.query = {
        token: latestToken,
      };
    });

Parece que la autenticación del lado del servidor se estaba realizando antes de que se estableciera el nuevo token. Si obtiene el token sincrónicamente (obteniéndolo algún tiempo antes y almacenándolo, y luego recuperándolo en la devolución de llamada del oyente), el servidor obtiene el nuevo token de autenticación a tiempo para la autenticación de reconexión.

Tenemos un problema similar. Pero mi solución actual es disconnect desde el lado del servidor cuando falla la autenticación. al recibir el evento disconnect en el cliente, reconstruimos la consulta / encabezado con la llamada de promesa asíncrona. Cuando llega al evento reconnecting , ya tiene el nuevo valor en la consulta / encabezado.

Para futuros lectores:

El comportamiento de la opción query en Socket.IO v2 es un poco extraño, ya que se usa en ambos:

  • los parámetros de consulta (para la instancia de Manager)
  • el protocolo de enlace Socket.IO (pero solo para un espacio de nombres no predeterminado)

Así que no estoy seguro de cómo podríamos solucionarlo de una manera compatible con versiones anteriores ...

Tenga en cuenta que esto está arreglado en Socket.IO v3, ya que ahora puede usar la opción auth :

// plain object
const socket = io({
  auth: {
    token: "abc"
  }
});

// or with a function
const socket = io({
  auth: (cb) => {
    cb({
      token: "abc"
    });
  }
});

También debería funcionar con una función async :

const socket = io({
  auth: async (cb) => {
    cb({
      token: "abc"
    });
  }
});

Ver también:

¿Fue útil esta página
0 / 5 - 0 calificaciones