Socket.io-client: Socket.handshake.query als Funktion zulassen

Erstellt am 22. Mai 2017  ·  9Kommentare  ·  Quelle: socketio/socket.io-client

Sie wollen:

  • [x] einen Fehler melden
  • [ ] Feature anfordern

Aktuelles Verhalten

socket.handshake.query ermöglicht derzeit das Festlegen von Daten auf connect , kann jedoch nicht durch Verweis aktualisiert werden, bevor reconnect ausgelöst wurde. Dies führt zu Problemen beim Autorisieren einer Socket-Verbindung mit Aktualisierungstoken.

Schritte zum Reproduzieren (wenn das aktuelle Verhalten ein Fehler ist)

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

Wenn der Server neu gestartet wird und die Clients reconnect , kann das Token bei der erneuten Autorisierung des Sockets veraltet sein.

//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
   }
});

Erwartetes Verhalten

Abfrage als function zulassen:

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

Konfiguration

  • socket.io-Version: 2.0.1

Wie repariert man

Im aktuellen Socket-Konstruktor:

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

Kann wie folgt geändert werden:

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

Hilfreichster Kommentar

@reeltimedoktor derzeit sollten Sie in der Lage sein, das query Objekt beim reconnect_attempt Ereignis zu aktualisieren:

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

Alle 9 Kommentare

+1
Fix für Fehler #1086 sollte auch Ihr Problem lösen. Das Ändern der Abfrageoptionen nach erfolgreicher Verbindung funktionierte mit der älteren socket.io-client-Version, aber mit der aktuellen Version ging der Verweis auf das Abfrageobjekt verloren :(

@reeltimedoktor derzeit sollten Sie in der Lage sein, das query Objekt beim reconnect_attempt Ereignis zu aktualisieren:

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

Die Lösung von @darrachequesne scheint bei mir nicht zu funktionieren :(

Ich verwende socket.io-client Version 2.3.0 auf dem Client, mit einem Knotenserver mit socket.io Version 2.3.0 .

Auf dem Client mache ich das:

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

Und dann authentifiziert der Server das Token mit einer Middleware, die an io.use() (die dann ausgelöst werden sollte, wenn der Socket eine Verbindung oder erneute Verbindung herstellt, afaik?).

Im Moment schlägt die Serverauthentifizierung beim erneuten Verbinden fehl und sagt, dass das Token abgelaufen ist - es scheint, dass das neue Token socket.io.opts.query.token nicht richtig zugewiesen wurde - haben Sie eine Idee, warum?

Danke :)

Update: Anscheinend gibt es im Socket-Objekt eine Reihe verschiedener Stellen, an denen das Auth-Token gespeichert ist, zB socket.io.engine.query.token , socket.io.engine.transport.query.token . Diese werden nicht automatisch ausgefüllt, wenn Sie socket.io.opts.query.token festlegen. Das Ändern dieser Werte hat jedoch immer noch keinen Einfluss auf das, was die Server „sehen“ – es sieht immer noch nur das alte Token.

Das Token scheint auch als URL-Parameter in einigen der URL-Felder im Socket-Objekt enthalten zu sein. Vielleicht müssen diese auch aktualisiert werden?

Nach der Untersuchung weiter, dass es scheint , die Token - Einstellung auf socket.io.opts.query.token ausreichend ist , das Token für die erneute Authentifizierung ändern auf der Wiederverbindung - scheint etwas anderes das Problem für meine Anwendung zu sein, vielleicht etwas mit Feuerbasis Auth - Token Generation zu tun. Für alle anderen, die darauf stoßen , @darrachequesne !

Ok, ich denke, ich habe es behoben - Sie müssen sicherstellen, dass Sie das neue Token synchron im Callback "reconnect_attempt" erhalten, dh tun Sie dies nicht:

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

Es scheint, als ob die serverseitige Authentifizierung durchgeführt wurde, bevor das neue Token festgelegt wurde. Wenn Sie das Token synchron abrufen (indem Sie es einige Zeit zuvor abrufen und speichern und dann einfach im Listener-Callback abrufen), erhält der Server das neue Authentifizierungstoken rechtzeitig für die Wiederverbindungsauthentifizierung.

mit "socket.io-client": "3.0.4" erhalte ich einen TS2341: Property 'opts' is private and only accessible within class 'Manager'. Fehler. Ich verwende "typescript": "4.1.3"
image

Ok, ich denke, ich habe es behoben - Sie müssen sicherstellen, dass Sie das neue Token _synchron_ im Callback 'reconnect_attempt' erhalten, dh tun Sie dies nicht:

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

Es scheint, als ob die serverseitige Authentifizierung durchgeführt wurde, bevor das neue Token festgelegt wurde. Wenn Sie das Token synchron abrufen (indem Sie es einige Zeit zuvor abrufen und speichern und dann einfach im Listener-Callback abrufen), erhält der Server das neue Authentifizierungstoken rechtzeitig für die Wiederverbindungsauthentifizierung.

Wir haben ein ähnliches Problem. Aber meine aktuelle Problemumgehung besteht darin, disconnect von der Serverseite aus zu verwenden, wenn die Authentifizierung fehlschlägt. Beim Empfang des disconnect Ereignisses auf dem Client rekonstruieren wir die Abfrage/den Header mit dem asynchronen Promise-Aufruf. Wenn es das Ereignis reconnecting , hat es bereits den neuen Wert in der Abfrage/im Header.

Für zukünftige Leser:

Das Verhalten der Option query in Socket.IO v2 ist etwas seltsam, da sie in beiden verwendet wird:

  • die Abfrageparameter (für die Manager-Instanz)
  • der Socket.IO-Handshake (aber nur für einen nicht standardmäßigen Namespace)

Ich bin mir also nicht sicher, wie wir das abwärtskompatibel beheben könnten...

Bitte beachten Sie, dass dies in Socket.IO v3 behoben ist, da Sie jetzt die Option auth :

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

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

Es sollte auch mit einer async Funktion funktionieren:

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

Siehe auch:

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen