Socket.io-client: Autoriser socket.handshake.query à être une fonction

Créé le 22 mai 2017  ·  9Commentaires  ·  Source: socketio/socket.io-client

Tu veux:

  • [x] signaler un bogue
  • [ ] demander une fonctionnalité

Comportement actuel

socket.handshake.query permet actuellement de définir les données sur connect , mais ne peut pas être mis à jour par référence avant que reconnect soit déclenché. Cela provoque des problèmes lors de l'autorisation d'une connexion socket avec des jetons d'actualisation.

Étapes à reproduire (si le comportement actuel est un bug)

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

Si le serveur est redémarré et les clients reconnect , le jeton peut être obsolète lors de la réautorisation du 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
   }
});

Comportement attendu

Autoriser la requête à être un function :

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

Installer

  • version socket.io : 2.0.1

Comment réparer

Dans le constructeur Socket actuel :

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

Peut être changé en ceci :

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

Commentaire le plus utile

@reeltimedoktor actuellement, vous devriez pouvoir mettre à jour l'objet query sur l'événement reconnect_attempt :

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

Tous les 9 commentaires

+1
Le correctif du bogue #1086 devrait également résoudre votre problème. La modification des options de requête après une connexion réussie fonctionnait avec l'ancienne version du client socket.io, mais avec la version actuelle, la référence à l'objet de requête est perdue :(

@reeltimedoktor actuellement, vous devriez pouvoir mettre à jour l'objet query sur l'événement reconnect_attempt :

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

La solution de @darrachequesne ne semble pas fonctionner pour moi :(

Je suis sur la version socket.io-client 2.3.0 sur le client, avec un serveur de nœuds avec la version socket.io 2.3.0 .

Sur le client, je fais ceci :

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

Et puis le serveur authentifie le jeton à l'aide d'un middleware passé à io.use() (qui devrait alors se déclencher lorsque le socket se connecte ou se reconnecte, n'est-ce pas ?).

Pour le moment, l'authentification du serveur ne parvient pas à se reconnecter, indiquant que le jeton a expiré - il semble que le nouveau jeton n'est pas correctement affecté à socket.io.opts.query.token -

Merci :)

Mise à jour : il semble qu'il y ait un tas d'endroits différents dans l'objet socket où le jeton d'authentification est stocké, par exemple socket.io.engine.query.token , socket.io.engine.transport.query.token . Ceux-ci ne sont pas automatiquement renseignés lorsque vous définissez socket.io.opts.query.token . Cependant, leur modification n'affecte toujours pas ce que les serveurs "voient" - ils ne voient toujours que l'ancien jeton.

Le jeton semble également être inclus en tant que paramètre d'URL dans certains des champs d'URL de l'objet socket. Peut-être que ceux-ci doivent être mis à jour aussi?

Après avoir approfondi nos recherches, il semble que définir le jeton sur socket.io.opts.query.token soit suffisant pour modifier le jeton pour la réauthentification lors de la reconnexion - autre chose semble être le problème pour mon application, peut-être quelque chose à voir avec la génération de jetons d'authentification firebase. Alors pour tous ceux qui rencontrent ça, la solution de @darrachequesne fonctionne !

D'accord, je pense que je l'ai corrigé - vous devez vous assurer que vous obtenez le nouveau jeton de manière synchrone dans le rappel 'reconnect_attempt', c'est-à-dire ne faites pas ceci :

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

Il semble que l'authentification côté serveur ait été effectuée avant que le nouveau jeton ne soit défini. Si vous obtenez le jeton de manière synchrone (en l'obtenant quelque temps auparavant et en le stockant, puis en le récupérant simplement dans le rappel de l'écouteur), le serveur obtient le nouveau jeton d'authentification à temps pour l'authentification de reconnexion.

avec "socket.io-client": "3.0.4" TS2341: Property 'opts' is private and only accessible within class 'Manager'. erreur "typescript": "4.1.3"
image

D'accord, je pense que je l'ai corrigé - vous devez vous assurer que vous obtenez le nouveau jeton _synchrone_ dans le rappel 'reconnect_attempt', c'est-à-dire ne faites pas ceci :

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

Il semble que l'authentification côté serveur ait été effectuée avant que le nouveau jeton ne soit défini. Si vous obtenez le jeton de manière synchrone (en l'obtenant quelque temps auparavant et en le stockant, puis en le récupérant simplement dans le rappel de l'écouteur), le serveur obtient le nouveau jeton d'authentification à temps pour l'authentification de reconnexion.

Nous avons un problème similaire. Mais ma solution de contournement actuelle consiste à disconnect côté serveur lorsque l'authentification échoue. lors de la réception disconnect événement reconnecting , il a déjà la nouvelle valeur dans la requête/en-tête.

Pour les futurs lecteurs :

Le comportement de l'option query dans Socket.IO v2 est un peu étrange, car elle est utilisée dans les deux :

  • les paramètres de la requête (pour l'instance Manager)
  • la poignée de main Socket.IO (mais uniquement pour un espace de noms autre que celui par défaut)

Je ne sais donc pas comment nous pourrions le réparer de manière rétrocompatible...

Veuillez noter que cela est corrigé dans Socket.IO v3, car vous pouvez désormais utiliser l'option auth :

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

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

Cela devrait également fonctionner avec une fonction async :

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

Voir également:

Cette page vous a été utile?
0 / 5 - 0 notes