Заголовки HTTP в API клиента Websockets - PullRequest
153 голосов
/ 06 декабря 2010

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

Тем не менее, похоже, что в спецификации должна быть поддержка этих заголовков .

Кто-нибудь знает, как этого добиться?

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

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

Ответы [ 8 ]

167 голосов
/ 06 декабря 2010

Обновлено 2x

Краткий ответ: Нет, можно указать только путь и поле протокола.

Более длинный ответ:

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

Заголовок Sec-WebSocket-Protocol (который иногда расширяется доиспользуется в аутентификации, специфичной для 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

Обычным способом достижения аутентификации / авторизации WebSocket является внедрение системы создания билетов, в которой страница, на которой размещается клиент WebSocket, запрашивает билет с сервера, а затем передает этот билет во время настройки соединения WebSocket либо в строке URL / запроса, либо вполе протокола или требуется в качестве первого сообщения после установления соединения.Затем сервер разрешает продолжение соединения только в том случае, если заявка действительна (существует, еще не использовалась, IP-адрес клиента закодирован в совпадениях с заявкой, отметка времени в заявке недавно и т. Д.).Вот сводка информации о безопасности WebSocket: https://devcenter.heroku.com/articles/websocket-security

Раньше обычная аутентификация была опцией, но она устарела, и современные браузеры не отправляют заголовок, даже если он указан.

Базовая информация об аутентификации (устарела) :

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

var ws = new WebSocket("ws://username:password@example.com")

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

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

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

Спасибо Дмитрию Франку за базовую аутентификацию ответ

30 голосов
/ 07 января 2017

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

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

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


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

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

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

20 голосов
/ 05 февраля 2018

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

var authToken = 'R3YKZFKBVi';

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

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

Получите заголовки соединения запроса:

Cookie: X-Authorization=R3YKZFKBVi
16 голосов
/ 04 марта 2017

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

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

Этот URL-адрес действителенно - конечно - вам нужно изменить код своего сервера для его анализа.

12 голосов
/ 09 марта 2016

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

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

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

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

4 голосов
/ 11 октября 2018

Отправка заголовка авторизации невозможна.

Присоединение параметра запроса токена является опцией.Однако в некоторых случаях может быть нежелательно отправлять основной токен входа в виде обычного текста в качестве параметра запроса, поскольку он более непрозрачен, чем использование заголовка, и в конечном итоге будет зарегистрирован, кто знает где.Если это вызывает у вас проблемы с безопасностью, альтернативой является использование вторичного токена JWT только для содержимого веб-сокета .

Создайте конечную точку REST для генерации этого JWT , к которому, конечно, могут обращаться только пользователи, аутентифицированные с помощью вашего основного токена для входа (переданного через заголовок).JWT веб-сокета может быть настроен не так, как ваш токен входа, например, с более коротким тайм-аутом, поэтому безопаснее отправлять его в качестве параметра запроса на обновление.

Создайте отдельный JwtAuthHandler для того же маршрута, который вы зарегистрировали в SockJS eventbusHandler на .Сначала убедитесь, что ваш обработчик аутентификации зарегистрирован, чтобы вы могли проверить токен веб-сокета в вашей базе данных (JWT должен быть каким-то образом связан с вашим пользователем в бэкэнде).

1 голос
/ 01 июня 2017

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

Клиент:

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...
0 голосов
/ 08 января 2017

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

var WebSocketClient = require('websocket').client;
var ws = new WebSocketClient();
ws.connect(url, '', headers);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...