Nagłówki HTTP w Websockets client API

Wygląda na to, że łatwo jest dodać niestandardowe nagłówki HTTP do klienta websocket za pomocą dowolnego klienta nagłówka HTTP, który to obsługuje, ale nie mogę znaleźć, jak to zrobić z JSON API.

Wydaje się jednak, że powinno być wsparcie tych nagłówków w spec .

Czy ktoś wie jak to osiągnąć?
var ws = new WebSocket("ws://example.com/service");

W szczególności, muszę być w stanie wysłać nagłówek autoryzacji HTTP.

Author: MidnightLightning, 2010-12-05

11 answers

Aktualizacja 2x

Krótka odpowiedź: nie, można podać tylko pole path i protocol.

Dłuższa odpowiedź:

Nie ma metody w JavaScript WebSockets API do określania dodatkowych nagłówków dla klienta/przeglądarki do wysłania. Ścieżka HTTP ("GET /xyz") i nagłówek protokołu ("sec-WebSocket-Protocol") mogą być określone w konstruktorze WebSocket.

Nagłówek sec-WebSocket-Protocol (który jest czasami rozszerzany do użycia w WebSocket specific authentication) jest generowane z opcjonalnego drugiego argumentu do konstruktora WebSocket:

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

Powyższe wyniki w następujących nagłówkach:

Sec-WebSocket-Protocol: protocol

I

Sec-WebSocket-Protocol: protocol1, protocol2

Powszechnym wzorcem dla uzyskania uwierzytelniania/autoryzacji WebSocket jest wdrożenie systemu biletowego, w którym strona hostująca klienta WebSocket żąda zgłoszenia od serwera, a następnie przekazuje ten bilet podczas konfiguracji połączenia WebSocket w ciągu adresu URL/zapytania, w pole protocol lub wymagane jako pierwsza wiadomość po nawiązaniu połączenia. Serwer pozwala na kontynuowanie połączenia tylko wtedy, gdy bilet jest ważny (istnieje, nie był już używany, adres IP klienta zakodowany w meczach biletów, znacznik czasu w bilecie jest ostatni, itp.). Oto podsumowanie informacji o Zabezpieczeniach WebSocket: https://devcenter.heroku.com/articles/websocket-security

Podstawowe uwierzytelnianie było wcześniej opcją, ale jest to przestarzałe i nowoczesne przeglądarki nie wysyłaj nagłówka, nawet jeśli jest określony.

Podstawowe informacje o Auth (przestarzałe - nie działa):

Uwaga: poniższe informacje nie są już dokładne w żadnych nowoczesnych przeglądarkach.

Nagłówek autoryzacji jest generowany z pola username i password (lub po prostu username) Uri WebSocket:

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

Z powyższego wynika następujący nagłówek z zakodowanym łańcuchem" username:password " base64:

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Testowałem podstawowy auth w Chrome 55 i Firefox 50 i sprawdzono, że podstawowe informacje o auth są rzeczywiście negocjowane z serwerem (może to nie działać w Safari).

Podziękowania dla Dmitrija Franka za podstawowe auth odpowiedź

 248
Author: kanaka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-18 02:46:03

Bardziej alternatywne rozwiązanie, ale wszystkie nowoczesne przeglądarki wysyłają pliki cookie domeny wraz z połączeniem, więc za pomocą:

var authToken = 'R3YKZFKBVi';

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

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

Kończy się nagłówkiem połączenia żądania:

Cookie: X-Authorization=R3YKZFKBVi
 54
Author: Tim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-05 09:04:47

Problem z nagłówkiem autoryzacji HTTP można rozwiązać za pomocą:

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

Następnie zostanie ustawiony odpowiedni nagłówek HTTP autoryzacji podstawowej z podanymi username i password. Jeśli potrzebujesz podstawowej autoryzacji, to wszystko gotowe.


Chcę jednak użyć Bearer i uciekłem się do następującej sztuczki: łączę się z serwerem w następujący sposób:

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

I gdy mój kod po stronie serwera otrzyma podstawowy nagłówek autoryzacji z niepustą nazwą użytkownika i pustym hasłem, następnie interpretuje nazwę użytkownika jako token.

 36
Author: Dmitry Frank,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-07 13:18:45

Nie można dodawać nagłówków, ale jeśli chcesz przekazać wartości do serwera w momencie połączenia, możesz podać część ciągu zapytania w adresie url:

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

Ten adres URL jest poprawny, ale-oczywiście-musisz zmodyfikować kod serwera, aby go przeanalizować.

 21
Author: Gabriele Carioli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-04 14:02:05

Nie można wysyłać niestandardowego nagłówka, gdy chcesz nawiązać połączenie WebSockets za pomocą JavaScript WebSockets API. Możesz użyć nagłówków Subprotocols używając drugiego konstruktora klasy WebSocket:

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

A następnie możesz uzyskać nagłówki Subprotocols za pomocą klucza Sec-WebSocket-Protocol na serwerze.

Istnieje również ograniczenie, wartości nagłówków Subprotocols nie mogą zawierać przecinka (,) !

 20
Author: Saeed Zarinfam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-15 11:46:17

Wysyłanie nagłówka autoryzacji nie jest możliwe.

Dołączenie parametru token query jest opcją. Jednak w niektórych okolicznościach może być niepożądane wysyłanie głównego tokena logowania w postaci zwykłego tekstu jako parametru zapytania, ponieważ jest on bardziej nieprzezroczysty niż użycie nagłówka i kończy się zalogowaniem, który będzie tutaj. Jeśli chodzi o bezpieczeństwo, alternatywą jest użycie dodatkowego tokena JWT tylko dla rzeczy z gniazdami sieciowymi .

Utwórz punkt końcowy REST dla generowanie tego JWT, do którego oczywiście dostęp mają tylko użytkownicy uwierzytelnieni za pomocą głównego tokena logowania (przekazanego przez nagłówek). Web socket JWT może być skonfigurowany inaczej niż twój token logowania, np. z krótszym czasem oczekiwania, więc bezpieczniej jest wysłać zapytanie jako param żądania aktualizacji.

Utwórz osobny JwtAuthHandler dla tej samej trasy, na której zarejestrujesz sockjs eventbusHandler na. Upewnij się, że Twój handler auth jest zarejestrowany jako pierwszy, więc możesz sprawdzić Web socket Token przeciwko twojej bazie danych (JWT powinien być w jakiś sposób połączony z Twoim użytkownikiem w backendzie).

 20
Author: Norbert Schöpke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-10 22:53:18

Całkowicie zhakował to w ten sposób, dzięki odpowiedzi Kanaki.

Klient:

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

Serwer (używając w tym przykładzie Koa2, ale powinien być podobny wszędzie):

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...
 2
Author: Ryan Weiss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-01 17:55:42

In my situation (Azure Time Series Insights wss://)

Używając Opakowarki ReconnectingWebsocket i był w stanie osiągnąć dodawanie nagłówków za pomocą prostego rozwiązania:

socket.onopen = function(e) {
    socket.send(payload);
};

Gdzie ładowność w tym przypadku wynosi:

{
  "headers": {
    "Authorization": "Bearer TOKEN",
    "x-ms-client-request-id": "CLIENT_ID"
}, 
"content": {
  "searchSpan": {
    "from": "UTCDATETIME",
    "to": "UTCDATETIME"
  },
"top": {
  "sort": [
    {
      "input": {"builtInProperty": "$ts"},
      "order": "Asc"
    }], 
"count": 1000
}}}
 2
Author: Poopy McFartnoise,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-18 00:01:36

Możesz przekazać nagłówki jako wartość klucza w trzecim parametrze (opcje) wewnątrz obiektu. Przykład z Tokenem autoryzacji. Opuścił protokół (drugi parametr) jako null


ws = new WebSocket(‘ws://localhost’, null, { headers: { Authorization: token }})

Edit: wygląda na to, że takie podejście działa tylko z biblioteką nodejs, a nie ze standardową implementacją przeglądarki. Zostawić, bo niektórym może się to przydać.

 0
Author: Nodens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-05 08:15:06

Moja sprawa:

  • chcę połączyć się z produkcyjnym serwerem ws a www.mycompany.com/api/ws...
  • korzystanie z prawdziwych danych uwierzytelniających (plik cookie sesji)...
  • z lokalnej strony (localhost:8000).

Ustawienie document.cookie = "sessionid=foobar;path=/" nie pomoże, ponieważ domeny nie pasują.

Rozwiązanie :

Dodaj 127.0.0.1 wsdev.company.com do /etc/hosts.

W ten sposób twoja przeglądarka będzie używać plików cookie z mycompany.com podczas łączenia się z www.mycompany.com/api/ws, ponieważ łączysz się z ważnej subdomeny wsdev.company.com.

 -1
Author: Max Malysh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-13 19:41:33

Technicznie, będziesz wysyłać te nagłówki przez funkcję connect przed fazą aktualizacji protokołu. To mi się udało w projekcie nodejs:

var WebSocketClient = require('websocket').client;
var ws = new WebSocketClient();
ws.connect(url, '', headers);
 -4
Author: George,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-29 17:34:20