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.
//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
}
});
Permitir que la consulta sea function
:
io.connect("wss://socket.server.com", {
query : function(){
return {
token:"something dynamic"
}
}
});
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;
}
+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"
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:
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:
Comentario más útil
Actualmente @reeltimedoktor usted debe ser capaz de actualizar el
query
objeto enreconnect_attempt
evento: