it-swarm.com.de

HTTP-Header in der Websockets-Client-API

Sieht so aus, als ob es mit jedem HTTP-Header-Client, der dies unterstützt, einfach ist, benutzerdefinierte HTTP-Header zu Ihrem Websocket-Client hinzuzufügen. Ich kann jedoch nicht feststellen, wie dies mit der JSON-API möglich ist.

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

Hat jemand eine Ahnung, wie man es erreicht?

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

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

158

2x aktualisiert

Kurze Antwort: Nein, nur der Pfad und das Protokollfeld können 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 Protokollheader ("Sec-WebSocket-Protocol") können im WebSocket-Konstruktor angegeben werden.

Der Sec-WebSocket-Protocol-Header (der manchmal für die Verwendung bei der websocketspezifischen Authentifizierung erweitert wird) 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"]);

Die obigen Ergebnisse führen zu den folgenden Überschriften:

Sec-WebSocket-Protocol: protocol

und

Sec-WebSocket-Protocol: protocol1, protocol2

Ein gängiges Muster für das Erreichen der WebSocket-Authentifizierung/-Autorisierung besteht darin, ein Ticketingsystem zu implementieren, bei dem die Seite, auf der sich der WebSocket-Client befindet, ein Ticket vom Server anfordert und dieses Ticket dann beim Einrichten der WebSocket-Verbindung entweder in der URL/Abfragezeichenfolge im Protokollfeld weitergibt. oder als erste Nachricht nach dem Verbindungsaufbau erforderlich. Der Server lässt dann nur zu, dass die Verbindung fortgesetzt wird, wenn das Ticket gültig ist (existiert, noch nicht verwendet wurde, die Client-IP in Ticket-Übereinstimmungen verschlüsselt ist, der Zeitstempel im Ticket neu ist usw.). Hier finden Sie eine Zusammenfassung der WebSocket-Sicherheitsinformationen: https://devcenter.heroku.com/articles/websocket-security

Früher war die Standardauthentifizierung eine Option, dies wurde jedoch abgelehnt, und moderne Browser senden den Header nicht, selbst wenn er angegeben ist.

Basic Auth Info (veraltet) :

Der Authorization-Header wird aus dem Feld Benutzername und Kennwort (oder nur Benutzername) des WebSocket-URI generiert:

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

Das Obige ergibt den folgenden Header mit der codierten Zeichenfolge "Benutzername: Kennwort" base64:

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Ich habe die Basisauthentifizierung in Chrome 55 und Firefox 50) getestet und festgestellt, dass die Basisauthentifizierungsinformationen tatsächlich mit dem Server ausgehandelt wurden (dies funktioniert möglicherweise nicht in Safari).

Vielen Dank an Dmitry Frank für die grundlegende Autorisierung Antwort

172
kanaka

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

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

Anschließend wird mit den angegebenen username und password ein geeigneter HTTP-Header für die Basisautorisierung festgelegt. Wenn Sie eine Basisautorisierung benötigen, sind Sie bereit.


Ich möchte jedoch Bearer verwenden und habe auf den folgenden Trick zurückgegriffen: Ich verbinde mich wie folgt mit dem Server:

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

Und wenn mein Code auf der Serverseite einen Basic Authorization-Header mit einem nicht leeren Benutzernamen und einem leeren Kennwort erhält, interpretiert er den Benutzernamen als Token.

31
Dmitry Frank

Eine alternative Lösung, aber alle modernen Browser senden die Domain-Cookies zusammen mit der Verbindung. Verwenden Sie dazu:

var authToken = 'R3YKZFKBVi';

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

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

Beenden Sie mit den Anforderungsverbindungs-Headern:

Cookie: X-Authorization=R3YKZFKBVi
20
Tim

Sie können keine Header hinzufügen. Wenn Sie jedoch zum Zeitpunkt 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 Sie müssen natürlich Ihren Servercode ändern, um sie zu analysieren.

17

Sie können keine benutzerdefinierten Header senden, wenn Sie eine WebSockets-Verbindung mit der JavaScript-WebSockets-API herstellen möchten. Sie können Subprotocols -Header mit dem zweiten WebSocket-Klassenkonstruktor verwenden:

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

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

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

12
Saeed Zarinfam

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 Haupt-Login-Token im Klartext als Abfrageparameter zu senden, da es undurchsichtiger als die Verwendung eines Headers ist und überall protokolliert wird. Wenn dies für Sie Sicherheitsbedenken aufwirft, eine Alternative ist die Verwendung eines sekundären JWT-Tokens nur für das Web-Socket-Zeug.

Erstellen Sie einen REST Endpunkt zum Generieren dieser JWT, auf den natürlich nur Benutzer zugreifen können, die mit Ihrem primären Anmeldetoken authentifiziert sind (über Header übertragen). Der Web-Socket-JWT kann anders konfiguriert werden als Ihr Login-Token, z. B. mit einem kürzeren Timeout. Es ist also sicherer, ihn als Abfrageparameter Ihrer Upgrade-Anfrage zu senden.

Erstellen Sie einen separaten JwtAuthHandler für dieselbe Route, auf der Sie den SockJS-EventbusHandler registrieren. Stellen Sie sicher, dass Ihr Auth-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).

5

Dank Kanakas Antwort wurde es total gehackt.

Klient:

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

Server (in diesem Beispiel mit Koa2, 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...
1
Ryan Weiss

Technisch werden Sie diese Header vor der Protokollaktualisierungsphase über die Verbindungsfunktion senden. Dies funktionierte für mich in einem nodejs Projekt:

var WebSocketClient = require('websocket').client;
var ws = new WebSocketClient();
ws.connect(url, '', headers);
0
George