HTTP-Header in der Websockets-Client-API

Lesezeit: 11 Minuten

HTTP Header in der Websockets Client API
Julien Genestoux

Es sieht so aus, als wäre es einfach, benutzerdefinierte HTTP-Header zu Ihrem Websocket-Client mit jedem HTTP-Header-Client hinzuzufügen, der dies unterstützt, aber ich kann nicht finden, wie das mit der JSON-API geht.

Es scheint jedoch, dass es Unterstützung geben sollte diese Header in der Spezifikation.

Hat jemand eine Ahnung, wie man das erreicht?

var ws = new WebSocket("ws://example.com/service");

Insbesondere muss ich in der Lage sein, einen HTTP-Autorisierungsheader zu senden.

  • Ich denke, eine gute Lösung besteht darin, dem WebSocket zu erlauben, sich ohne Autorisierung zu verbinden, aber dann zu blockieren und auf dem Server zu warten, um die Autorisierung vom WebSocket zu erhalten, der Autorisierungsinformationen in seinem onopen-Ereignis überträgt.

    – Splitter

    28. Dezember 2015 um 15:57 Uhr

  • Der Vorschlag von @Motes scheint am besten zu passen. Es war sehr einfach, einen Autorisierungsaufruf von onOpen aus zu tätigen, mit dem Sie den Socket basierend auf der Autorisierungsantwort akzeptieren/ablehnen können. Ich habe ursprünglich versucht, ein Authentifizierungstoken im Sec-WebSocket-Protocol-Header zu senden, aber das fühlt sich wie ein Hack an.

    – Batteriesäure

    29. Oktober 2017 um 3:59 Uhr

  • @Motes Hallo, könnten Sie den Teil “Blockieren und auf dem Server warten” erklären? Sie meinen so etwas wie keine Nachrichten verarbeiten, bis eine “auth” -Nachricht vorhanden ist?

    – Himal

    18. August 2019 um 4:44 Uhr

  • @Himal, ja, das Serverdesign darf zu Beginn der Verbindung keine Daten senden oder andere Daten als die Autorisierung akzeptieren.

    – Splitter

    18. August 2019 um 10:37 Uhr

  • @Motes Danke für die Antwort. Der blockierende Teil hat mich etwas verwirrt, da Sie meines Wissens nach den Anfang nicht blockieren können connect Anfrage. Ich verwende Django-Kanäle am Backend und habe es so konzipiert, dass es die Verbindung akzeptiert connect Veranstaltung. es setzt dann ein “is_auth”-Flag in der receive event (wenn es eine gültige Authentifizierungsnachricht sieht). Wenn das is_auth-Flag nicht gesetzt ist und es sich nicht um eine Authentifizierungsnachricht handelt, wird die Verbindung geschlossen.

    – Himal

    18. August 2019 um 14:40 Uhr

1646309114 240 HTTP Header in der Websockets Client API
Kanaka

2x aktualisiert

Kurze Antwort: Nein, es können nur Pfad und Protokollfeld angegeben werden.

Längere Antwort:

Es gibt keine Methode im JavaScript WebSockets-API um zusätzliche Header anzugeben, die der Client/Browser senden soll. Der HTTP-Pfad („GET /xyz“) und der Protokoll-Header („Sec-WebSocket-Protocol“) können im WebSocket-Konstruktor angegeben werden.

Der Sec-WebSocket-Protocol-Header (der manchmal erweitert wird, um in der Websocket-spezifischen Authentifizierung verwendet zu werden) wird aus dem optionalen zweiten Argument für den WebSocket-Konstruktor generiert:

var ws = new WebSocket("ws://example.com/path", "protocol");
var ws = new WebSocket("ws://example.com/path", ["protocol1", "protocol2"]);

Das Obige führt zu den folgenden Headern:

Sec-WebSocket-Protocol: protocol

und

Sec-WebSocket-Protocol: protocol1, protocol2

Ein gängiges Muster zum Erreichen der WebSocket-Authentifizierung/Autorisierung besteht darin, ein Ticketsystem zu implementieren, bei dem die Seite, auf der der WebSocket-Client gehostet wird, ein Ticket vom Server anfordert und dieses Ticket dann während des WebSocket-Verbindungsaufbaus entweder in der URL/Abfragezeichenfolge, im Protokollfeld, oder als erste Meldung nach Verbindungsaufbau erforderlich. Der Server erlaubt dann nur dann die Fortsetzung der Verbindung, wenn das Ticket gültig ist (vorhanden, noch nicht verwendet wurde, Client-IP im Ticket codiert, Zeitstempel im Ticket aktuell usw.). Hier ist eine Zusammenfassung der WebSocket-Sicherheitsinformationen: https://devcenter.heroku.com/articles/websocket-security

Die Standardauthentifizierung war früher eine Option, die jedoch veraltet ist, und moderne Browser senden den Header nicht, selbst wenn er angegeben ist.

Grundlegende Authentifizierungsinformationen (veraltet – nicht mehr funktionsfähig):

HINWEIS: Die folgenden Informationen sind in modernen Browsern nicht mehr korrekt.

Der Autorisierungsheader wird aus dem Benutzernamen- und Kennwortfeld (oder nur dem Benutzernamen) des WebSocket-URI generiert:

var ws = new WebSocket("ws://username:[email protected]")

Das Obige führt zu folgendem Header mit der base64-codierten Zeichenfolge “username:password”:

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Ich habe die grundlegende Authentifizierung in Chrome 55 und Firefox 50 getestet und überprüft, ob die grundlegenden Authentifizierungsinformationen tatsächlich mit dem Server ausgehandelt werden (dies funktioniert möglicherweise nicht in Safari).

Vielen Dank an Dmitry Frank für die grundlegende Authentifizierungsantwort

  • Ich bin auf das gleiche Problem gestoßen. Schade, dass diese Standards so schlecht integriert sind. Sie würden erwarten, dass sie sich die XHR-API ansehen, um Anforderungen für die WebSockets-API zu finden (da WebSockets und XHR verwandt sind), aber es scheint, dass sie die API nur auf einer eigenen Insel entwickeln.

    – Elektrotelekram

    1. Mai 2012 um 14:26 Uhr

  • @eleotlecram, treten Sie der HyBi-Arbeitsgruppe bei und schlagen Sie sie vor. Die Gruppe ist öffentlich zugänglich und es wird laufend an Folgeversionen des Protokolls gearbeitet.

    – Kanaka

    1. Mai 2012 um 18:59 Uhr

  • @Charlie: Wenn Sie den Server vollständig kontrollieren, ist dies eine Option. Der üblichere Ansatz besteht darin, ein Ticket/Token von Ihrem normalen HTTP-Server zu generieren und den Client dann das Ticket/Token senden zu lassen (entweder als Abfragezeichenfolge im Websocket-Pfad oder als erste Websocket-Nachricht). Der Websocket-Server validiert dann, dass das Ticket/Token gültig ist (nicht abgelaufen ist, nicht bereits verwendet wurde, von derselben IP stammt wie bei der Erstellung usw.). Außerdem glaube ich, dass die meisten Websockets-Clients die grundlegende Authentifizierung unterstützen (möglicherweise nicht genug für Sie). Mehr Info: devcenter.heroku.com/articles/websocket-security

    – Kanaka

    4. Juni 2014 um 17:57 Uhr

  • Ich denke, es ist beabsichtigt. Ich habe den Eindruck, dass die Implementierung absichtlich Anleihen bei HTTP macht, sie aber vom Design her so weit wie möglich voneinander trennt. Der Text in der Spezifikation fährt fort: „Das Design beschränkt WebSocket jedoch nicht auf HTTP, und zukünftige Implementierungen könnten einen einfacheren Handshake über einen dedizierten Port verwenden, ohne das gesamte Protokoll neu zu erfinden. Dieser letzte Punkt ist wichtig, da die Verkehrsmuster des interaktiven Messaging dies tun entspricht nicht genau dem Standard-HTTP-Datenverkehr und kann einige Komponenten zu ungewöhnlichen Lasten führen.”

    Benutzer1441149

    14. September 2016 um 18:54 Uhr


  • Leider scheint das in Edge nicht zu funktionieren. Danke MS :/

    – Geschwister

    21. Februar 2017 um 11:07 Uhr

Eher eine alternative Lösung, aber alle modernen Browser senden die Domain-Cookies zusammen mit der Verbindung, also verwenden Sie:

var authToken = 'R3YKZFKBVi';

document.cookie="X-Authorization=" + authToken + '; path=/';

var ws = new WebSocket(
    'wss://localhost:9000/wss/'
);

Am Ende mit den Verbindungsheadern der Anfrage:

Cookie: X-Authorization=R3YKZFKBVi

  • Was ist, wenn sich die WS-Server-URI von der Client-URI unterscheidet?

    – Dänisch

    7. Mai 2020 um 0:11 Uhr

  • @Danish Nun, das funktioniert nicht, da Sie keine Cookies für andere Domänen clientseitig setzen können

    – Tofandel

    3. Juli 2020 um 20:12 Uhr

  • Sie können jedoch einen HTTP-Dienst einrichten, der ein Sitzungscookie auf dem entsprechenden Pfad setzt, und diesen aufrufen, bevor Sie Ihren Websocket starten. Rufen Sie an, sagen Sie, https://example.com/loginund lassen Sie die Antwort ein Cookie setzen /wss dann new WebSocket("wss://example.com/wss") startet seine Handshake-Anforderung mit dem entsprechenden Cookie. Beachten Sie, dass die Devtools das Cookie möglicherweise nicht anzeigen, es aber dennoch gesendet werden sollte.

    – Kodierer

    9. Juli 2020 um 12:52 Uhr

  • Websocket-Anfragen unterliegen nicht der gleichen Ursprungsrichtlinie. Durch das Senden der Authentifizierung als Cookie wird Ihre Anwendung für Hijacking geöffnet. Sehen christian-schneider.net/CrossSiteWebSocketHijacking.html

    – Declan Shanaghy

    19. Oktober 2020 um 18:43 Uhr

  • Christian Schneider (der Autor des obigen Artikels) schlägt vor, CSRF-Tokens zu verwenden, um den anfänglichen HTTP-Handshake zu schützen, wenn ein Authentifizierungs-Cookie verwendet wird: ws = new WebSocket("wss://example.com/wss?csrftoken=<token>")

    – Alex Buchatski

    30. März 2021 um 10:31 Uhr


Das Problem mit dem HTTP-Autorisierungsheader kann wie folgt behoben werden:

var ws = new WebSocket("ws://username:[email protected]/service");

Dann wird ein richtiger HTTP-Header für die grundlegende Autorisierung mit dem bereitgestellten festgelegt username und password. Wenn Sie eine Basisautorisierung benötigen, sind Sie bereit.


Ich möchte benutzen Bearer jedoch, und ich habe zu folgendem Trick gegriffen: Ich verbinde mich wie folgt mit dem Server:

var ws = new WebSocket("ws://[email protected]/service");

Und wenn mein Code auf der Serverseite den Basic Authorization-Header mit einem nicht leeren Benutzernamen und einem leeren Passwort empfängt, interpretiert er den Benutzernamen als Token.

  • Ich versuche die von dir vorgeschlagene Lösung. Aber ich kann nicht sehen, dass der Authorization-Header zu meiner Anfrage hinzugefügt wird. Ich habe es mit verschiedenen Browsern versucht, zB Chrome V56, Firefox V51.0. Ich betreibe meinen Server auf meinem Localhost. Die Websocket-URL lautet also “ws://myusername:[email protected]:8080/mywebsocket”. Irgendeine Idee, was falsch sein könnte? Danke

    – Lerne zu leben

    11. März 2017 um 21:15 Uhr


  • Ist es sicher, Token über eine URL zu übertragen?

    – Loskutow Ilja

    4. Mai 2017 um 18:02 Uhr

  • Ich stimme @LearnToLive zu – ich habe dies mit wss verwendet (zB wss://user:[email protected]/ws) und bekam keine Authorization Header auf der Serverseite (unter Verwendung von Chrome Version 60)

    – Benutzer9645

    4. August 2017 um 13:59 Uhr

  • Ich habe das gleiche Problem wie @LearnToLive und @user9645; Weder Chrome noch Firefox fügen den Autorisierungsheader hinzu, wenn sich der URI in der befindet wss://user:[email protected] Format. Wird dies von Browsern nicht unterstützt oder läuft etwas mit dem Handshake schief?

    – David Kaczyński

    2. Februar 2018 um 20:42 Uhr

  • Die Verwendung dieser URLs http://username:[email protected] wird abgeschrieben. developer.mozilla.org/en-US/docs/Web/HTTP/Authentication. Vielleicht funktioniert es deshalb auch nicht mit Websockets!

    – Dachstein

    19. August 2018 um 18:14 Uhr


Das Senden des Authorization-Headers ist nicht möglich.

Das Anhängen eines Token-Abfrageparameters ist eine Option. Unter bestimmten Umständen kann es jedoch unerwünscht sein, Ihr Hauptanmeldetoken im Klartext als Abfrageparameter zu senden, da dies undurchsichtiger ist als die Verwendung eines Headers und am Ende protokolliert wird, wer weiß wo. Wenn dies Sicherheitsbedenken für Sie aufwirft, Eine Alternative ist die Verwendung eines sekundären JWT-Tokens nur für die Web-Socket-Sachen.

Erstellen Sie einen REST-Endpunkt zum Generieren dieses JWT, auf die natürlich nur Benutzer zugreifen können, die sich mit Ihrem primären Login-Token (übermittelt per Header) authentifiziert haben. Das Web-Socket-JWT kann anders als Ihr Login-Token konfiguriert werden, z. B. mit einem kürzeren Timeout, sodass es sicherer ist, es als Abfrageparameter Ihrer Upgrade-Anfrage herumzusenden.

Erstellen Sie einen separaten JwtAuthHandler für dieselbe Route, auf der Sie den SockJS-EventbusHandler registrieren. Stellen Sie sicher, dass Ihr Authentifizierungs-Handler zuerst registriert ist, damit Sie das Web-Socket-Token mit Ihrer Datenbank vergleichen können (das JWT sollte irgendwie mit Ihrem Benutzer im Backend verknüpft sein).

1646309114 231 HTTP Header in der Websockets Client API
Said Zarinfam

Sie können keinen benutzerdefinierten Header senden, wenn Sie eine WebSockets-Verbindung mithilfe der JavaScript-WebSockets-API herstellen möchten. Sie können verwenden Subprotocols Header mithilfe des zweiten WebSocket-Klassenkonstruktors:

var ws = new WebSocket("ws://example.com/service", "soap");

und dann können Sie die Subprotocols-Header mit abrufen Sec-WebSocket-Protocol Schlüssel auf dem Server.

Es gibt auch eine Einschränkung, Ihre Unterprotokoll-Header-Werte dürfen kein Komma enthalten (,) !

  • Darf ein Jwt ein Komma enthalten?

    – CESCO

    20. Oktober 2016 um 3:52 Uhr

  • Ich glaube nicht. JWT besteht aus drei base64-codierten Payloads, die jeweils durch einen Punkt getrennt sind. Ich glaube, dies schließt die Möglichkeit eines Kommas aus.

    – BillyBBone

    12. März 2017 um 2:02 Uhr


  • Ich habe das implementiert und es funktioniert – fühlt sich nur komisch an. Danke

    – Batteriesäure

    10. April 2017 um 2:14 Uhr

  • Schlagen Sie vor, dass wir die verwenden Sec-WebSocket-Protocol Header als Alternative zum Authorization Header?

    – rw

    14. Mai 2018 um 7:33 Uhr

Sie können keine Header hinzufügen, aber wenn Sie im Moment der Verbindung nur Werte an den Server übergeben müssen, können Sie einen Teil der Abfragezeichenfolge in der URL angeben:

var ws = new WebSocket("ws://example.com/service?key1=value1&key2=value2");

Diese URL ist gültig, aber natürlich müssen Sie Ihren Servercode ändern, um sie zu analysieren.

  • Darf ein Jwt ein Komma enthalten?

    – CESCO

    20. Oktober 2016 um 3:52 Uhr

  • Ich glaube nicht. JWT besteht aus drei base64-codierten Payloads, die jeweils durch einen Punkt getrennt sind. Ich glaube, dies schließt die Möglichkeit eines Kommas aus.

    – BillyBBone

    12. März 2017 um 2:02 Uhr


  • Ich habe das implementiert und es funktioniert – fühlt sich nur komisch an. Danke

    – Batteriesäure

    10. April 2017 um 2:14 Uhr

  • Schlagen Sie vor, dass wir die verwenden Sec-WebSocket-Protocol Header als Alternative zum Authorization Header?

    – rw

    14. Mai 2018 um 7:33 Uhr

HTTP Header in der Websockets Client API
Ryan Weiss

Habe es dank Kanakas Antwort total gehackt.

Klient:

var ws = new WebSocket(
    'ws://localhost:8080/connect/' + this.state.room.id, 
    store('token') || cookie('token') 
);

Server (mit Koa2 in diesem Beispiel, sollte aber überall ähnlich sein):

var url = ctx.websocket.upgradeReq.url; // can use to get url/query params
var authToken = ctx.websocket.upgradeReq.headers['sec-websocket-protocol'];
// Can then decode the auth token and do any session/user stuff...

  • Übergibt dies Ihr Token nicht einfach in dem Abschnitt, in dem Ihr Client ein oder mehrere spezifische Protokolle anfordern soll? Ich kann das zum Laufen bringen, auch kein Problem, aber ich habe mich entschieden, dies nicht zu tun und lieber das zu tun, was Motes vorgeschlagen hat, und zu blockieren, bis das Authentifizierungstoken auf onOpen () gesendet wird. Das Überladen des Protokollanforderungsheaders scheint mir falsch zu sein, und da meine API für den öffentlichen Gebrauch bestimmt ist, denke ich, dass es für die Benutzer meiner API etwas verwirrend sein wird.

    – Jay

    27. Juni 2017 um 9:57 Uhr

923190cookie-checkHTTP-Header in der Websockets-Client-API

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy