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.
//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
}
});
Autoriser la requête à être un function
:
io.connect("wss://socket.server.com", {
query : function(){
return {
token:"something dynamic"
}
}
});
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;
}
+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"
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 :
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:
Commentaire le plus utile
@reeltimedoktor actuellement, vous devriez pouvoir mettre à jour l'objet
query
sur l'événementreconnect_attempt
: