encabezados HTTP en API de cliente Websockets


106

Parece que es fácil agregar encabezados HTTP personalizados a su cliente websocket con cualquier cliente de encabezado HTTP que lo admita, pero no puedo encontrar cómo hacerlo con la API JSON.

Sin embargo, parece que debería haber soporte these headers in the spec.

¿Alguien tiene una pista sobre cómo lograrlo?

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

Específicamente, necesito poder enviar un encabezado de autorización HTTP.

+5

creo que una buena solución es permitir que el WebSocket para conectar sin autorización, pero luego bloquear y esperar en el servidor para recibir la autorización de la WebSocket que transmitirá la información de autorización en su caso AlAbrir. 28 dic. 152015-12-28 15:57:16

  0

La sugerencia de @Motes parece ser la mejor opción. Fue muy fácil hacer una llamada de autorización desde onOpen que le permite aceptar/rechazar el socket en función de la respuesta de autorización. Intenté originalmente enviar el token de autenticación en el encabezado Sec-WebSocket-Protocol, pero eso parece un hack. 29 oct. 172017-10-29 03:59:46

121

Actualizado

Respuesta corta: No, pero autenticación básica funciona

más larga respuesta:

No existe un método en el JavaScript WebSockets API para especificar cabeceras adicionales para el cliente/navegador mandar. Sin embargo, la ruta HTTP ("GET/xyz"), el encabezado básico de autenticación ("Autorización") y el encabezado del protocolo ("Sec-WebSocket-Protocol") se pueden especificar en el constructor WebSocket.

La cabecera de autorización se genera a partir del campo de nombre de usuario y la contraseña (o simplemente nombre de usuario) de la WebSocket URI:

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

Los resultados anteriores en la siguiente cabecera con la cadena "nombre de usuario: contraseña" base64:

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ= 

he probado autenticación básica en Chrome 55 y Firefox 50 y verificado que la información de autenticación de base es negociado con el servidor (esto puede no funcionar en Safari).

La cabecera Sec-WebSocket-Protocolo (que a veces se extiende para ser utilizado en la autenticación específica WebSocket) se genera a partir del segundo argumento opcional al constructor WebSocket:

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

Los resultados anteriores en los siguientes encabezados :

Sec-WebSocket-Protocol: protocol 

y

Sec-WebSocket-Protocol: protocol1, protocol2 

Gracias a Dmitry Frank's por la autenticación básica answer

+18

Me he encontrado con el mismo problema. Lástima que estos estándares estén tan mal integrados. Es de esperar que consulten la API de XHR para encontrar los requisitos (ya que WebSockets y XHR están relacionados) para la API de WebSockets, pero parece que solo están desarrollando la API en una isla por sí mismos. 01 may. 122012-05-01 14:26:24

+3

@eleotlecram, únete al grupo de trabajo HyBi y proponlo. El grupo está abierto al público y hay trabajos en curso para versiones posteriores del protocolo. 01 may. 122012-05-01 18:59:49

  0

¿Sería una mala idea usar los valores de encabezado de protocolo para enviar (por ejemplo) un hash de autorización? Leyendo aquí - http://stackoverflow.com/questions/7363095/javascript-and-websockets-using-specific-protocol - no parece una mala idea, pero me pregunto cuáles son las implicaciones. 04 jun. 142014-06-04 16:20:07

+4

@Charlie: si controla completamente el servidor, esa es una opción. El enfoque más común es generar un ticket/token de su servidor HTTP normal y luego hacer que el cliente envíe el ticket/token (ya sea como una cadena de consulta en la ruta websocket o como el primer mensaje websocket). El servidor websocket valida entonces que el ticket/token es válido (no ha caducado, no se ha utilizado ya, proviene de la misma IP que cuando se creó, etc.). Además, creo que la mayoría de los clientes de websockets admiten autenticación básica (aunque puede que no sea suficiente). Más información: https://devcenter.heroku.com/articles/websocket-security 04 jun. 142014-06-04 17:57:22

  0

Digest auth funciona con WebSockets también. 28 dic. 152015-12-28 18:07:21

  0

@eleotiecram Según rfc6455: El protocolo WebSocket está diseñado para reemplazar las tecnologías de comunicación bidireccional existentes que usan HTTP como capa de transporte para beneficiarse de la infraestructura existente (proxies, filtrado, autenticación). [...........] El protocolo WebSocket intenta abordar los objetivos de las tecnologías HTTP bidireccionales existentes en el contexto de la infraestructura HTTP existente; como tal, está diseñado para funcionar a través de los puertos HTTP 80 y 443, así como para admitir intermediarios HTTP y , incluso si esto implica cierta complejidad específica del entorno actual . 14 sep. 162016-09-14 18:47:26

+3

Supongo que es por diseño. Tengo la impresión de que la implementación se toma prestada intencionalmente de HTTP, pero los mantengo separados tanto como sea posible por diseño. El texto en la especificación continúa: "Sin embargo, el diseño no limita WebSocket a HTTP, y las implementaciones futuras podrían usar un saludo más simple sobre un puerto dedicado sin reinventar todo el protocolo. Este último punto es importante porque los patrones de tráfico de interactivos mensajes no coinciden estrechamente con el tráfico HTTP estándar y pueden inducir cargas inusuales en algunos componentes. " 14 sep. 162016-09-14 18:54:02

  0

2016 y este sigue siendo el caso :( 07 oct. 162016-10-07 15:04:43

  0

Si no podemos agregar un encabezado personalizado, ¿podemos al menos modificar un encabezado no personalizado, por ejemplo, 'Cookie'? 09 dic. 162016-12-09 07:07:36

  0

Hay una manera de establecer el encabezado HTTP de Autorización básica, vea mi 07 ene. 172017-01-07 13:36:36

+1

Desafortunadamente esto no parece funcionar en Edge. Gracias, MS:/ 21 feb. 172017-02-21 11:07:32

  0

'ws: // nombre de usuario: contraseña @ ejemplo.com' este patrón no funciona en Safari, pero funciona en cromo, ff 25 jul. 172017-07-25 13:58:18


7

No se puede enviar un encabezado personalizado cuando se desea establecer la conexión WebSockets mediante javascript WebSockets API. Puede utilizar Subprotocols encabezados utilizando el segundo constructor de la clase WebSocket:

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

y entonces se puede obtener utilizando las cabeceras subprotocolos Sec-WebSocket-Protocol clave en el servidor.

También hay una limitación, los valores de los encabezados de Subprotocols no pueden contener una coma (,).

+1

Mayo un Jwt contiene una coma? 20 oct. 162016-10-20 03:52:51

  0

No lo creo. JWT consiste en tres cargas útiles codificadas en base64, cada una separada por un punto. Creo que esto descarta la posibilidad de una coma. 12 mar. 172017-03-12 02:02:34

+1

Implementé esto y funciona, solo se siente raro, gracias 10 abr. 172017-04-10 02:14:28


14

problema Autorización de cabecera HTTP se puede tratar con lo siguiente:

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

Entonces, una cabecera HTTP de Autorización adecuada de base se fijará con la proporcionada username y password. Si necesita la Autorización básica, entonces ya está todo listo.


Quiero usar Bearer sin embargo, y recurrieron a la siguiente truco: me conecto al servidor de la siguiente manera:

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

Y cuando mi código en el lado del servidor recibe Autorización de cabecera básico con nombre de usuario no vacío y contraseña vacía, entonces interpreta el nombre de usuario como un token.

+4

Estoy intentando la solución sugerida por usted. Pero no puedo ver el encabezado de autorización que se agrega a mi solicitud. Lo he intentado. usando diferentes navegadores, p. Chrome V56, Firefox V51.0 Estoy ejecutando mi servidor en mi servidor local. por lo que la url websocket es "ws: // myusername: mypassword @ localhost: 8080/mywebsocket". ¿Alguna idea de lo que podría estar mal? Gracias 11 mar. 172017-03-11 21:15:37

+3

¿Es seguro transferir token a través de la url? 04 may. 172017-05-04 18:02:03

+1

@Mergasov Lo mismo es cuestionable para la Autenticación básica ¿no? 25 may. 172017-05-25 06:27:28

+1

¿No se ocultarían los encabezados básicos de autenticación si se usa una conexión segura, mientras que la URL estaría abierta a todo el mundo que husmee? 04 jun. 172017-06-04 03:02:51

+1

El nombre de usuario vacío/ignorado y la contraseña no vacía como token pueden ser mejores porque los nombres de usuario pueden registrarse. 22 jun. 172017-06-22 01:28:12

+2

Estoy de acuerdo con @LearnToLive - Lo usé con wss (por ej. 'Wss: // usuario: contraseña @ myhost.com/ws') y no recibí el encabezado' Authorization' en el servidor (usando la versión 60 de Chrome) 04 ago. 172017-08-04 13:59:53

  0

@rslite En una conexión segura, todo, incluida la URL, está oculto dentro del túnel seguro. 08 nov. 172017-11-08 05:39:08

  0

Tengo el mismo problema que @LearnToLive y @ user9645; ni Chrome ni Firefox están agregando el encabezado de autorización cuando el URI está en el formato 'wss: // user: pass @ host'. ¿No es compatible con navegadores, o algo anda mal con el apretón de manos? 02 feb. 182018-02-02 20:42:57

  0

Mismo problema aquí. Sin encabezado de autorización. Esto es el infierno. 11 feb. 182018-02-11 02:02:07


0

Técnicamente, enviará estos encabezados a través de la función de conexión antes de la fase de actualización del protocolo.

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

¡Ojalá las personas agreguen comentarios cuando rechazan una respuesta, como StackOverflow les pide! Es difícil saber si algunos ignorantes cuya configuración particular no funcionó, o si esto definitivamente no funciona bajo ninguna circunstancia, es una desventaja. Al mismo tiempo, George: es dudoso que esto funcione en los navegadores.Si esto funciona en nodejs o en algún otro motor JS, es un detalle importante para agregar a su respuesta. 25 may. 172017-05-25 01:00:07

+1

Esto es para el cliente de websocket en npm (para nodo). https://www.npmjs.com/package/websocket En general, esto sería exactamente lo que estoy buscando, pero en el navegador. 16 ago. 172017-08-16 22:50:00

  0

Se bajó debido a que este parámetro de encabezados está en la capa de protocolo WebSocket, y la pregunta es acerca de los encabezados HTTP. 30 nov. 172017-11-30 13:49:05


7

No se puede agregar encabezados pero, si lo que necesita para pasar valores al servidor en el momento de la conexión, puede especificar una parte cadena de consulta en la url:

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

esa URL es válido pero, por supuesto, deberá modificar el código del servidor para analizarlo.

+3

debe tener cuidado con esta solución, la cadena de consulta puede ser interceptada, registrada en proxies, etc. por lo que pasar información confidencial (usuarios/contraseña/tokens de autenticación) de esta manera no será lo suficientemente segura. 23 abr. 172017-04-23 13:46:50

+1

@Nir con WSS la cadena de consulta probablemente sea segura 29 may. 172017-05-29 14:49:06

+4

ws es texto sin formato. Usando el protocolo ws, cualquier cosa puede ser interceptada. 30 may. 172017-05-30 15:05:48

  0

@SebastienLorber no es seguro utilizar cadena de consulta, no se cifra, lo mismo se aplica a HTTPS, pero como se usa el protocolo "ws: // ...", realmente no importa. 20 sep. 172017-09-20 00:32:13

+1

@ Lu4 la cadena de consulta está encriptada, pero hay una serie de otras razones para no agregar datos confidenciales como parámetros de consulta 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 pirateado así, gracias a la respuesta de kanaka.

Cliente:

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

servidor (usando Koa2 en este ejemplo, pero debería ser similar donde sea):

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

¿Esto no pasa solo su token en la sección donde se supone que su cliente solicitar uno o más protocolos específicos? Puedo hacer que esto funcione, no hay problema también, pero decidí no hacer esto y más bien hacer lo que motes sugirió y bloquear hasta que el token de autenticación se envíe en onOpen(). Sobrecargar el encabezado de solicitud de protocolo me parece incorrecto, y como mi API es para consumo público, creo que va a ser algo confuso para los consumidores de mi API. 27 jun. 172017-06-27 09:57:24


0

Más de una solución alternativa, pero todos los navegadores modernos envían las cookies de dominio a lo largo de con la conexión, entonces usando:

var authToken = 'R3YKZFKBVi'; 

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

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

Termine con los encabezados de conexión de solicitud:

Cookie: X-Authorization=R3YKZFKBVi