web-dev-qa-db-ja.com

WebsocketsクライアントAPIのHTTPヘッダー

これをサポートする任意のHTTPヘッダークラ​​イアントを使用してwebsocketクライアントにカスタムHTTPヘッダーを追加するのは簡単に見えますが、JSON APIでそれを行う方法は見つかりません。

それでも、サポートが必要なようです 仕様のこれらのヘッダー

誰もそれを達成する方法についての手がかりを持っていますか?

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

具体的には、HTTP Authorizationヘッダーを送信できる必要があります。

158

2x更新

短い答え:いいえ、指定できるのはパスとプロトコルフィールドのみです。

より長い答え:

JavaScriptにはメソッドがありません WebSockets API クライアント/ブラウザーが送信する追加のヘッダーを指定するためのものです。 HTTPパス( "GET/xyz")およびプロトコルヘッダー( "Sec-WebSocket-Protocol")は、WebSocketコンストラクターで指定できます。

Sec-WebSocket-Protocolヘッダー(Websocket固有の認証で使用されるように拡張される場合があります)は、WebSocketコンストラクターのオプションの2番目の引数から生成されます。

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

以前は基本認証はオプションでしたが、これは廃止されており、最新のブラウザはヘッダーが指定されていても送信しません。

基本認証情報(非推奨)

Authorizationヘッダーは、WebSocket URIのユーザー名とパスワード(または単にユーザー名)フィールドから生成されます。

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

上記の結果、文字列「username:password」base64がエンコードされた次のヘッダーが生成されます。

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Chrome 55およびFirefox 50で基本認証をテストし、基本認証情報が実際にサーバーとネゴシエートされることを確認しました(これはSafariでは機能しない可能性があります)。

Dmitry Frankの基本認証に感謝します answer

172
kanaka

HTTP Authorizationヘッダーの問題は、次の方法で対処できます。

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

次に、提供されたusernameおよびpasswordを使用して、適切な基本認証HTTPヘッダーが設定されます。基本認証が必要な場合は、準備は完了です。


Bearerを使用したいのですが、次のトリックに頼りました。次のようにサーバーに接続します。

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

そして、サーバー側の私のコードは、空でないユーザー名と空のパスワードを持つ基本認証ヘッダーを受け取ると、ユーザー名をトークンとして解釈します。

31
Dmitry Frank

より多くの代替ソリューションですが、最新のブラウザはすべて、接続とともにドメインCookieを送信するため、以下を使用します。

var authToken = 'R3YKZFKBVi';

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

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

リクエスト接続ヘッダーで終わります:

Cookie: X-Authorization=R3YKZFKBVi
20
Tim

ヘッダーを追加することはできませんが、接続時にサーバーに値を渡す必要がある場合は、URLでクエリ文字列部分を指定できます。

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

そのURLは有効ですが、もちろん、サーバーコードを変更して解析する必要があります。

17

JavaScript WebSockets APIを使用してWebSockets接続を確立する場合、カスタムヘッダーを送信できません。 2番目のWebSocketクラスコンストラクターを使用して、Subprotocolsヘッダーを使用できます。

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

サーバーのSec-WebSocket-Protocolキーを使用してサブプロトコルヘッダーを取得できます。

サブプロトコルヘッダーの値にコンマ(,)を含めることはできません!

12
Saeed Zarinfam

Authorizationヘッダーを送信することはできません。

トークンクエリパラメータの付加はオプションです。ただし、状況によっては、メインのログイントークンをクエリテキストとしてプレーンテキストで送信するのは望ましくない場合があります。ヘッダーを使用するよりも不透明であり、whoknowswhereに記録されることになります。これによりセキュリティ上の懸念が生じた場合は、代替手段は、WebソケットにのみセカンダリJWTトークンを使用することです

このJWTを生成するためのRESTエンドポイントを作成します。これはもちろん、プライマリログイントークン(ヘッダー経由で送信)で認証されたユーザーのみがアクセスできます。 WebソケットJWTは、ログイントークンとは異なるように構成できます。より短いタイムアウトで、アップグレードリクエストのクエリパラメータとして送信する方が安全です。

SockJS eventbusHandlerを登録するのと同じルートに個別のJwtAuthHandlerを作成します。認証ハンドラーが最初に登録されていることを確認して、Webソケットトークンをデータベースに対してチェックできるようにします(JWTは何らかの方法でバックエンドでユーザーにリンクされる必要があります)。

5

Kanakaの回答のおかげで、このように完全にハッキングされました。

クライアント:

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
Ryan Weiss

技術的には、プロトコルのアップグレードフェーズの前に、接続機能を介してこれらのヘッダーを送信します。これはnodejsプロジェクトで私のために働いた:

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