Intestazioni HTTP nell'API client Websockets


106

Sembra che sia facile aggiungere intestazioni HTTP personalizzate al client Websocket con qualsiasi client di intestazione HTTP che supporti ciò, ma non riesco a trovare come farlo con l'API JSON.

Eppure, sembra che ci dovrebbe essere il supporto these headers in the spec.

Qualcuno ha un indizio su come raggiungerlo?

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

In particolare, devo essere in grado di inviare un'intestazione di autorizzazione HTTP.

+5

penso che una buona soluzione è quella di permettere al WebSocket per collegare senza autorizzazione, ma poi bloccare e attendere sul server per ricevere l'autorizzazione dal websocket che trasmetterà le informazioni di autorizzazione nel suo evento OnOpen. 28 dic. 152015-12-28 15:57:16

  0

Il suggerimento di @Motes sembra essere la soluzione migliore. È stato molto facile effettuare una chiamata di autorizzazione da onOpen che consente di accettare/rifiutare il socket in base alla risposta di autorizzazione. Inizialmente, ho tentato di inviare un token di autenticazione nell'intestazione di Sec-WebSocket-Protocol, ma mi sembra un trucco. 29 ott. 172017-10-29 03:59:46

121

Aggiornato

Risposta breve: No, ma autenticazione di base funziona

Longer risposta:

Non esiste un metodo in JavaScript WebSockets API per specificare intestazioni aggiuntive per il cliente/navigatore inviare. Tuttavia il percorso HTTP ("GET/xyz"), l'intestazione di autenticazione di base ("Autorizzazione") e l'intestazione del protocollo ("Sec-WebSocket-Protocol") possono essere specificati nel costruttore WebSocket.

L'intestazione di autorizzazione è generata dal campo nome utente e password (o solo username) del WebSocket URI:

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

I risultati sopra riportati nella seguente intestazione con la stringa "username: password" base64 codificato:

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ= 

ho testato autenticazione di base in Chrome 55 e Firefox 50 e verificato che le informazioni di autenticazione di base è infatti negoziato con il server (questo potrebbe non funzionare in Safari).

L'intestazione Sec-WebSocket-Protocol (che a volte è esteso per essere utilizzato in di autenticazione specifico websocket) è generato dal secondo argomento opzionale al costruttore WebSocket:

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

I risultati sopra riportati nei seguenti intestazioni :

Sec-WebSocket-Protocol: protocol 

e

Sec-WebSocket-Protocol: protocol1, protocol2 

Grazie a Dmitry Frank's per l'autenticazione di base answer

+18

Ho incontrato lo stesso problema. Peccato che questi standard siano così poco integrati. Ci si aspetta che guardino all'API XHR per trovare i requisiti (dal momento che WebSockets e XHR sono correlati) per l'API WebSockets, ma sembra che stiano semplicemente sviluppando l'API su un'isola da sola. 01 mag. 122012-05-01 14:26:24

+3

@eleotlecram, unisciti al gruppo di lavoro HyBi e proponilo. Il gruppo è aperto al pubblico e sono in corso lavori per le versioni successive del protocollo. 01 mag. 122012-05-01 18:59:49

  0

Sarebbe una cattiva idea utilizzare i valori dell'intestazione del protocollo per inviare (per esempio) un hash di autorizzazione? Leggendo qui - http://stackoverflow.com/questions/7363095/javascript-and-websockets-using-specific-protocol - non sembra una cattiva idea, ma mi chiedo quali siano le implicazioni. 04 giu. 142014-06-04 16:20:07

+4

@ Charlie: se controlli completamente il server, questa è un'opzione. L'approccio più comune è generare un ticket/token dal proprio server HTTP normale e quindi fare in modo che il client invii il ticket/token (come stringa di query nel percorso websocket o come primo messaggio Websocket). Il server WebSocket quindi convalida che il ticket/token è valido (non è scaduto, non è già stato utilizzato, proviene dallo stesso IP di quando è stato creato, ecc.). Inoltre, credo che la maggior parte dei client websockets supporti l'autenticazione di base (potrebbe non essere sufficiente per te). Maggiori informazioni: https://devcenter.heroku.com/articles/websocket-security 04 giu. 142014-06-04 17:57:22

  0

L'autenticazione del digest funziona anche con WebSockets. 28 dic. 152015-12-28 18:07:21

  0

@eleotiecram Secondo rfc6455: WebSocket Protocol è progettato per sostituire le tecnologie di comunicazione bidirezionale esistenti che utilizzano HTTP come transportlayer per beneficiare dell'infrastruttura esistente (proxy, filtraggio, autenticazione). [...........] Il protocollo WebSocket tenta di soddisfare gli obiettivi delle tecnologie HTTP bidirezionali esistenti nel contesto dell'infrastruttura HTTP esistente; in quanto tale, è progettato per funzionare su tramite le porte HTTP 80 e 443 e per supportare i proxy HTTP e gli intermediari , anche se questo implica una certa complessità specifica per l'ambiente corrente . 14 set. 162016-09-14 18:47:26

+3

Immagino che sia di design. Ho l'impressione che l'implementazione stia prendendo in prestito intenzionalmente da HTTP ma li tenga separati il ​​più possibile dalla progettazione. Il testo nella specifica continua: "Tuttavia, il progetto non limita WebSocket a HTTP e le future implementazioni potrebbero utilizzare un semplice handshake su una porta dedicata senza reinventare l'intero protocollo. Questo ultimo punto è importante perché i modelli di traffico di La messaggistica non corrisponde esattamente al traffico HTTP standard e può indurre carichi insoliti su alcuni componenti. " 14 set. 162016-09-14 18:54:02

  0

2016 e questo è ancora il caso :( 07 ott. 162016-10-07 15:04:43

  0

Se non possiamo aggiungere un'intestazione personalizzata, possiamo almeno modificare un'intestazione non personalizzata, ad esempio "Cookie"? 09 dic. 162016-12-09 07:07:36

  0

C'è un modo per impostare l'intestazione HTTP dell'autorizzazione di base, vedere la mia risposta 07 gen. 172017-01-07 13:36:36

+1

Purtroppo questo non sembra funzionare in Edge. Grazie, MS:/ 21 feb. 172017-02-21 11:07:32

  0

'ws: // username: password @ example.com' questo modello non funziona in Safari, ma funziona in chrome, ff 25 lug. 172017-07-25 13:58:18


7

Non è possibile inviare intestazione personalizzata quando si desidera stabilire una connessione WebSockets utilizzando l'API javascript WebSockets. È possibile utilizzare le intestazioni Subprotocols utilizzando il secondo costruttore della classe WebSocket:

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

e quindi è possibile ottenere le intestazioni Subprotocols utilizzando Sec-WebSocket-Protocol chiave sul server.

C'è anche una limitazione, i valori delle intestazioni dei Sottoprotocolli non possono contenere una virgola (,)!

+1

Maggio un Jwt contiene una virgola? 20 ott. 162016-10-20 03:52:51

  0

Non credo. JWT è costituito da tre payload con codifica Base64, ciascuno separato da un punto .Certo che questo esclude la possibilità di una virgola. 12 mar. 172017-03-12 02:02:34

+1

Ho implementato questo e funziona Stranamente grazie 10 apr. 172017-04-10 02:14:28


14

Autorizzazione HTTP problema intestazione può essere affrontato con il seguente:

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

Poi, una corretta intestazione HTTP di base Autorizzazione sarà fissato con l'apposita username e password. Se hai bisogno di un'autorizzazione di base, allora sei pronto.


voglio usare Bearer tuttavia, e ho fatto ricorso al seguente trucco: mi collego al server come segue:

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

E quando il mio codice sul lato server riceve intestazione di base Autorizzazione con nome utente non vuoto e password vuota, quindi interpreta il nome utente come token.

+4

Sto provando la soluzione suggerita da te, ma non riesco a vedere l'intestazione dell'autorizzazione aggiunta alla mia richiesta. utilizzando diversi browser, ad es. Chrome V56, Firefox V51.0 Sto eseguendo il mio server sul mio localhost. quindi l'URL websocket è "ws: // nomeutente: mypassword @ localhost: 8080/mywebsocket". Qualche idea di cosa potrebbe essere sbagliato? Grazie 11 mar. 172017-03-11 21:15:37

+3

È sicuro trasferire il token tramite l'url? 04 mag. 172017-05-04 18:02:03

+1

@Mergasov la stessa cosa è discutibile per l'autenticazione di base, giusto? 25 mag. 172017-05-25 06:27:28

+1

Le intestazioni di autenticazione di base non dovrebbero essere nascoste se viene utilizzata una connessione protetta, mentre l'URL potrebbe essere aperto a tutti spiando? 04 giu. 172017-06-04 03:02:51

+1

Il nome utente vuoto/ignorato e la password non vuota come token potrebbero essere migliori perché i nomi utente potrebbero essere registrati. 22 giu. 172017-06-22 01:28:12

+2

Sono d'accordo con @LearnToLive - L'ho usato con wss (ad esempio 'wss: // user: password @ myhost.com/ws') e non ho ottenuto l'intestazione' Authorization' sul lato server (utilizzando la versione 60 di Chrome) 04 ago. 172017-08-04 13:59:53

  0

@rslite In una connessione sicura, tutto compreso l'URL è nascosto all'interno del tunnel sicuro. 08 nov. 172017-11-08 05:39:08

  0

Ho lo stesso problema di @LearnToLive e @ user9645; né chrome né firefox aggiungono l'intestazione di autorizzazione quando l'URI si trova nel formato 'wss: // user: pass @ host'. Non è supportato dai browser, o c'è qualcosa che non va nella stretta di mano? 02 feb. 182018-02-02 20:42:57

  0

Lo stesso problema qui. Nessuna intestazione di autorizzazione. Questo è l'inferno. 11 feb. 182018-02-11 02:02:07


0

Tecnicamente, si invieranno queste intestazioni tramite la funzione di connessione prima della fase di aggiornamento del protocollo.

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

Vorrei che le persone aggiungessero commenti quando inoltrano una risposta, come StackOverflow chiede loro di farlo! È difficile dire se è stato downvoted da qualche ignorante il cui particolare setup non ha funzionato, o se questo sicuramente non funzionerà in nessuna circostanza. Allo stesso tempo, George: È dubbio che funzionerà nei browser.Se funziona in nodejs o in qualche altro motore JS, questo è un dettaglio importante da aggiungere alla tua risposta. 25 mag. 172017-05-25 01:00:07

+1

Questo è per il client websocket in npm (per nodo). https://www.npmjs.com/package/websocket Nel complesso questo sarebbe esattamente quello che sto cercando, ma nel browser. 16 ago. 172017-08-16 22:50:00

  0

È downvoted perché questo parametro di intestazione sul livello di protocollo WebSocket e la domanda riguarda le intestazioni HTTP. 30 nov. 172017-11-30 13:49:05


7

Non è possibile aggiungere intestazioni, ma, se avete solo bisogno di passare i valori al server al momento della connessione, è possibile specificare una parte stringa di query sulla url:

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

tale URL è valido ma - ovviamente - è necessario modificare il codice del server per analizzarlo.

+3

deve fare attenzione con questa soluzione, la stringa di query può essere intercettata, i proxy registrati, ecc. In questo modo le informazioni sensibili (utenti/password/token di autenticazione) in questo modo non saranno abbastanza sicure. 23 apr. 172017-04-23 13:46:50

+1

@Nir con WSS la querystring dovrebbe probabilmente essere sicura 29 mag. 172017-05-29 14:49:06

+4

ws è testo normale. Usando il protocollo ws, qualsiasi cosa può essere intercettata. 30 mag. 172017-05-30 15:05:48

  0

@SebastienLorber non è sicuro usare la stringa di query che non viene crittografata lo stesso vale per HTTPS, ma dal momento che viene utilizzato il protocollo "ws: // ...", in realtà non importa. 20 set. 172017-09-20 00:32:13

+1

@ Lu4 la stringa di query è crittografata, ma esistono altri motivi per non aggiungere dati sensibili come parametri di ricerca URL https://stackoverflow.com/questions/499591/are-https-urls-encrypted/499594#499594 & https://blog.httpwatch.com/2009/02/20/how-secure-are-query-strings-over-https/ as refs 27 nov. 172017-11-27 19:53:18


0

Totalmente hackerato in questo modo, grazie alla risposta di kanaka.

Cliente:

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

Server (utilizzando Koa2 in questo esempio, ma dovrebbe essere simile ovunque):

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

Questo non fa passare il tuo token nella sezione in cui il tuo cliente dovrebbe richiedere uno o più protocolli specifici? Posso farlo funzionare, senza problemi, ma ho deciso di non farlo e piuttosto di fare ciò che Motes ha suggerito e di bloccare fino a quando il token di autenticazione non viene inviato su onOpen(). Sovraccaricare l'intestazione della richiesta del protocollo mi sembra sbagliato, e poiché la mia API è destinata al consumo pubblico, penso che sarà un po 'confusa per i consumatori della mia API. 27 giu. 172017-06-27 09:57:24


0

Più di una soluzione alternativa, ma tutti i browser moderni inviano i cookie di dominio lungo con la connessione, quindi utilizzando:

var authToken = 'R3YKZFKBVi'; 

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

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

Terminare con le intestazioni di connessione richiesta:

Cookie: X-Authorization=R3YKZFKBVi