HTTP-заголовки в API-интерфейсах Websockets


106

Похоже, что добавлять пользовательские заголовки HTTP к вашему клиенту websocket с помощью любого HTTP-заголовка клиента, который поддерживает это, легко, но я не могу найти, как это сделать с помощью JSON API.

Однако, похоже, что должна быть поддержка these headers in the spec.

У каждого есть ключ к тому, как его достичь?

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

В частности, мне нужно иметь возможность отправлять заголовок авторизации HTTP.

+5

Я думаю, что это хорошее решение, чтобы позволить WebSocket подключиться без авторизации, но затем блокировать и ждать на сервере, чтобы получать разрешение от WebSocket, который будет передавать информацию об авторизации в OnOpen случае. 28 дек. 152015-12-28 15:57:16

  0

Рекомендация @Motes, по-видимому, лучше всего подходит. Было очень просто сделать авторизационный вызов onOpen, который позволяет принимать/отклонять сокет на основе ответа авторизации. Сначала я попытался отправить токен аутентификации в заголовок Sec-WebSocket-Protocol, но это похоже на взлома. 29 окт. 172017-10-29 03:59:46

121

Обновлено

Короткий ответ: Нет, но основная авторизация работает

Longer ответ:

Там нет метода в JavaScript WebSockets API для указания дополнительных заголовков для клиента/браузера отправлять. Однако HTTP-путь («GET/xyz»), базовый заголовок auth («Авторизация») и заголовок протокола («Sec-WebSocket-Protocol») могут быть указаны в конструкторе WebSocket.

Заголовок авторизации генерируется из поля имя пользователя и пароль (или просто имя пользователя) из WebSocket URI:

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

Приведенные выше результаты в следующем заголовке со строкой «имя пользователя: пароль» в кодировке Base64:

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ= 

Я проверил основную авторизацию в браузере Chrome 55 и Firefox 50 и проверить, что основная информация аутентификации действительно вел переговоры с сервером (это может не работать в Safari).

Заголовок втор-WebSocket-протокола (который иногда распространяется для использования в WebSocket конкретной аутентификации) генерируется из необязательного второго аргумента конструктора WebSocket:

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

Приведенные выше результаты в следующих заголовков :

Sec-WebSocket-Protocol: protocol 

и

Sec-WebSocket-Protocol: protocol1, protocol2 

Спасибо Дмитрию Фрэнку за базовый auth answer

+18

Я столкнулся с той же проблемой. Жаль, что эти стандарты настолько плохо интегрированы. Вы ожидаете, что они рассмотрят API XHR для поиска требований (поскольку WebSockets и XHR связаны) для API WebSockets, но, похоже, они просто разрабатывают API на острове сами по себе. 01 май. 122012-05-01 14:26:24

+3

@eleotlecram, присоединитесь к рабочей группе HyBi и предложите ее. Группа открыта для общественности и продолжается работа над последующими версиями протокола. 01 май. 122012-05-01 18:59:49

  0

Было бы плохой идеей использовать значения заголовка протокола для отправки (например) хэша авторизации? Чтение здесь - http://stackoverflow.com/questions/7363095/javascript-and-websockets-using-specific-protocol - это не похоже на плохую идею, но я действительно задаюсь вопросом, каковы последствия. 04 июн. 142014-06-04 16:20:07

+4

@Charlie: если вы полностью контролируете сервер, это один из вариантов. Более общий подход - генерировать билет/токен с вашего обычного HTTP-сервера, а затем отправить клиенту билет/токен (либо в виде строки запроса в пути к веб-расписанию, либо в качестве первого сообщения веб-рассылки). Затем сервер websocket подтверждает, что билет/токен действителен (срок его действия еще не истек, он еще не использовался, исходящий от того же IP-адреса, что и при создании, и т. Д.). Кроме того, я считаю, что большинство клиентов веб-карт поддерживают базовый auth (может быть, для вас это не достаточно). Дополнительная информация: https://devcenter.heroku.com/articles/websocket-security 04 июн. 142014-06-04 17:57:22

  0

Digest auth также работает с WebSockets. 28 дек. 152015-12-28 18:07:21

  0

@eleotiecram Согласно rfc6455: Протокол WebSocket предназначен для замены существующих двунаправленных коммуникационных технологий, которые используют HTTP в качестве транспортного уровня для использования существующей инфраструктуры (прокси, фильтрация, аутентификация). [...........] Протокол WebSocket пытается решить задачи существующих двунаправленных HTTP-технологий в контексте существующей инфраструктуры HTTP; как таковой, он предназначен для работы через HTTP-порты 80 и 443, а также для поддержки HTTP-прокси и посредников, даже если это подразумевает определенную сложность, характерную для текущей среды . 14 сен. 162016-09-14 18:47:26

+3

Я думаю, его по дизайну. У меня создалось впечатление, что реализация намеренно заимствует из HTTP, но по своему дизайну они разделяют как можно больше. Текст в specificatio продолжается: «Однако дизайн не ограничивает использование WebSocket для HTTP, а в будущих реализациях может использоваться упрощенное рукопожатие по выделенному порту без повторного использования всего протокола. Этот последний момент важен, поскольку шаблоны трафика интерактивных обмен сообщениями не соответствует стандарту HTTP-трафика и может вызвать необычные нагрузки на некоторые компоненты ». 14 сен. 162016-09-14 18:54:02

  0

2016, и это все еще так :( 07 окт. 162016-10-07 15:04:43

  0

Если мы не можем добавить пользовательский заголовок, можем ли мы как минимум изменить нестандартный заголовок, например, «Cookie»? 09 дек. 162016-12-09 07:07:36

  0

Существует способ установки основного HTTP-заголовка авторизации, см. Мой ответ 07 янв. 172017-01-07 13:36:36

+1

К сожалению, это не работает в Edge. Спасибо, MS:/ 21 фев. 172017-02-21 11:07:32

  0

'ws: // имя пользователя: пароль @ example.com' этот шаблон не работает в Safari, но работает в chrome, ff 25 июл. 172017-07-25 13:58:18


7

Вы не можете отправить пользовательский заголовок, если хотите установить соединение с WebSockets, используя API-интерфейс javascript WebSockets. Вы можете использовать Subprotocols заголовки с помощью второго конструктора класса WebSocket:

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

, а затем вы можете получить заголовки субпротоколов с помощью Sec-WebSocket-Protocol ключа на сервере.

Существует также ограничение, ваши значения заголовков подпрограмм не могут содержать запятую (,)!

+1

May a Jwt содержит запятую? 20 окт. 162016-10-20 03:52:51

  0

Я не верю в это. JWT состоит из трех базовых нагрузок base64, каждый из которых разделен на период. Я считаю, что это исключает возможность запятой. 12 мар. 172017-03-12 02:02:34

+1

Я реализовал это, и он работает - просто чувствует weird. спасибо 10 апр. 172017-04-10 02:14:28


14

проблема заголовка HTTP авторизации можно решить с помощью следующих действий:

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

Затем правильный заголовок HTTP Basic Authorization будет установлен с прилагающимся username и password. Если вам нужна базовая авторизация, тогда вы все настроены.


Я хочу использовать Bearer однако, и я обратился к следующей уловке: я подключиться к серверу следующим образом:

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

И когда мой код на стороне сервера получает Основной заголовок авторизации с непустое имя пользователя и пустой пароль, тогда он интерпретирует имя пользователя как токен.

+4

Я пытаюсь предложить решение, предложенное вами. Но я не могу видеть заголовок авторизации, добавленный в мой запрос. он использует различные браузеры, например. Chrome V56, Firefox V51.0 Я запускаю свой сервер на своем локальном хосте. поэтому URL-адрес websocket равен «ws: // myusername: mypassword @ localhost: 8080/mywebsocket». Любая идея, что может быть неправильным? Спасибо 11 мар. 172017-03-11 21:15:37

+3

Безопасно ли передавать токен через URL-адрес? 04 май. 172017-05-04 18:02:03

+1

@Mergasov то же самое, что вопрос для базовой аутентификации прав? 25 май. 172017-05-25 06:27:28

+1

Не будут ли скрыты основные заголовки аутентификации, если будет использоваться безопасное соединение, в то время как URL-адрес будет открыт для всех пользователей? 04 июн. 172017-06-04 03:02:51

+1

Пустое/проигнорированное имя пользователя и непустой пароль, поскольку токен может быть лучше, потому что имена пользователей могут регистрироваться. 22 июн. 172017-06-22 01:28:12

+2

Я согласен с @LearnToLive - я использовал это с помощью wss (например, 'wss: // user: password @ myhost.com/ws') и не получил заголовка' Authorization' на стороне сервера (используя версию Chrome 60) 04 авг. 172017-08-04 13:59:53

  0

@rslite В безопасном соединении все, включая URL-адрес, скрывается внутри защищенного туннеля. 08 ноя. 172017-11-08 05:39:08

  0

У меня такая же проблема, как @LearnToLive и @ user9645; ни хром, ни firefox не добавляют заголовок авторизации, когда URI находится в формате 'wss: // user: pass @ host'. Это не поддерживается браузерами, или что-то не так с рукопожатием? 02 фев. 182018-02-02 20:42:57

  0

Такая же проблема здесь. Нет заголовка авторизации. Это ад. 11 фев. 182018-02-11 02:02:07


0

Технически вы отправляете эти заголовки через функцию подключения до этапа обновления протокола.

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

Я бы хотел, чтобы люди добавляли комментарии, когда они отвечали на вопрос, как StackOverflow просит их! Трудно сказать, было ли это замещено каким-то невежда, чья конкретная настройка для него не работала, или если это определенно не будет работать ни при каких обстоятельствах. В то же время Джордж: Сомнительно, что это будет работать в браузерах.Если это работает в nodejs или каком-то другом движке JS, это важная деталь, чтобы добавить к вашему ответу. 25 май. 172017-05-25 01:00:07

+1

Это для клиента websocket в npm (для узла). https://www.npmjs.com/package/websocket В целом это было бы именно то, что я ищу, но в браузере. 16 авг. 172017-08-16 22:50:00

  0

Он занижен, потому что этот параметр заголовков находится на уровне протокола WebSocket, и вопрос касается заголовков HTTP. 30 ноя. 172017-11-30 13:49:05


7

Вы не можете добавлять заголовки, но, если вам просто нужно передать значения на сервер в момент подключения, вы можете указать строку запроса часть на URL:

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

That URL действительно, но, конечно же, вам нужно будет изменить код сервера, чтобы проанализировать его.

+3

необходимо быть осторожным с этим решением, строка запроса может быть перехвачена, зарегистрирована в прокси-серверах и т. Д., Поэтому передача конфиденциальной информации (токены пользователей/пароля/аутентификации) таким образом не будет достаточно надежной. 23 апр. 172017-04-23 13:46:50

+1

@Nir с WSS querystring, вероятно, должен быть безопасным 29 май. 172017-05-29 14:49:06

+4

ws - это простой текст. Используя протокол ws, все может быть перехвачено. 30 май. 172017-05-30 15:05:48

  0

@SebastienLorber небезопасно использовать строку запроса, она не шифруется, то же самое относится к HTTPS, но поскольку используется протокол ws: // ..., это действительно не имеет значения. 20 сен. 172017-09-20 00:32:13

+1

@ Lu4 строка запроса зашифрована, но существует множество других причин не добавлять конфиденциальные данные в параметры 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/ как refs 27 ноя. 172017-11-27 19:53:18


0

Полностью взломал его так, благодаря ответу Канаки.

Клиент:

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

сервера (с помощью Koa2 в этом примере, но они должны быть похожи везде):

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

Разве это не просто передает ваш токен в разделе, где ваш клиент должен запросить один или несколько конкретных протоколов? Я могу заставить это работать, не проблема, но я решил не делать этого и скорее делать то, что предложил и блокировал Motes, пока токен auth не отправлен на onOpen(). Перегрузка заголовка запроса протокола кажется мне неправильной, и поскольку мой API для общественного потребления, я думаю, что это будет немного запутанным для потребителей моего API. 27 июн. 172017-06-27 09:57:24


0

Больше альтернативного решения, но все современные браузеры отправить куки домена по с подключением, поэтому с использованием:

var authToken = 'R3YKZFKBVi'; 

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

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

Завершите запрос с помощью соединительных разъемов:

Cookie: X-Authorization=R3YKZFKBVi