AWS IoT
開発者ガイド

MQTT over WebSocket プロトコル

AWS IoT では、MQTT over the WebSocket プロトコルがサポートされており、ブラウザーベースのアプリケーションは AWS の認証情報を使用して、AWS IoT に接続されたデバイスに対してデータを送受信できます。AWS の認証情報は、AWS 署名バージョン 4 を使用して指定されます。WebSocket サポートは、TCP ポート 443 で利用可能です。メッセージはほとんどのファイアウォールやウェブプロキシを通過できます。

WebSocket 接続は、HTTP GET リクエストを送信することで、クライアントで開始されます。使用する URL の形式は以下のとおりです。

wss://<endpoint>.iot.<region>.amazonaws.com/mqtt
wss

WebSocket プロトコルを指定します。

endpoint

AWS アカウント固有の AWS IoT エンドポイント。AWS IoT CLI describe-endpoint コマンドを使用して、このエンドポイントを見つけることができます。

リージョン

AWS アカウントの AWS リージョン。

mqtt

WebSocket プロトコルを介して MQTT メッセージを送信することを指定します。

サーバーが応答すると、クライアントはアップグレードリクエストを送信し、WebSocket プロトコルを使用して通信するようにサーバーに指示します。サーバーがアップグレードリクエストを受け入れた後、すべての通信は WebSocket プロトコルを使用して実行されます。使用する WebSocket 実装は、トランスポートプロトコルとして機能します。WebSocket プロトコルを介して送信するデータは MQTT メッセージです。

ウェブアプリケーションでの WebSocket プロトコルの使用

ほとんどのウェブブラウザーによって提供される WebSocket 実装では、HTTP ヘッダーの変更は許可されないため、クエリ文字列に署名バージョン 4 の情報を追加する必要があります。詳細については、「クエリ文字列への署名情報の追加」を参照してください。

以下の JavaScript では、署名バージョン 4 リクエストの生成時に使用されるいくつかのユーティリティ関数を定義しています。

/** * utilities to do sigv4 * @class SigV4Utils */ function SigV4Utils() {} SigV4Utils.getSignatureKey = function (key, date, region, service) { var kDate = AWS.util.crypto.hmac('AWS4' + key, date, 'buffer'); var kRegion = AWS.util.crypto.hmac(kDate, region, 'buffer'); var kService = AWS.util.crypto.hmac(kRegion, service, 'buffer'); var kCredentials = AWS.util.crypto.hmac(kService, 'aws4_request', 'buffer'); return kCredentials; }; SigV4Utils.getSignedUrl = function(host, region, credentials) { var datetime = AWS.util.date.iso8601(new Date()).replace(/[:\-]|\.\d{3}/g, ''); var date = datetime.substr(0, 8); var method = 'GET'; var protocol = 'wss'; var uri = '/mqtt'; var service = 'iotdevicegateway'; var algorithm = 'AWS4-HMAC-SHA256'; var credentialScope = date + '/' + region + '/' + service + '/' + 'aws4_request'; var canonicalQuerystring = 'X-Amz-Algorithm=' + algorithm; canonicalQuerystring += '&X-Amz-Credential=' + encodeURIComponent(credentials.accessKeyId + '/' + credentialScope); canonicalQuerystring += '&X-Amz-Date=' + datetime; canonicalQuerystring += '&X-Amz-SignedHeaders=host'; var canonicalHeaders = 'host:' + host + '\n'; var payloadHash = AWS.util.crypto.sha256('', 'hex') var canonicalRequest = method + '\n' + uri + '\n' + canonicalQuerystring + '\n' + canonicalHeaders + '\nhost\n' + payloadHash; var stringToSign = algorithm + '\n' + datetime + '\n' + credentialScope + '\n' + AWS.util.crypto.sha256(canonicalRequest, 'hex'); var signingKey = SigV4Utils.getSignatureKey(credentials.secretAccessKey, date, region, service); var signature = AWS.util.crypto.hmac(signingKey, stringToSign, 'hex'); canonicalQuerystring += '&X-Amz-Signature=' + signature; if (credentials.sessionToken) { canonicalQuerystring += '&X-Amz-Security-Token=' + encodeURIComponent(credentials.sessionToken); } var requestUrl = protocol + '://' + host + uri + '?' + canonicalQuerystring; return requestUrl; };

署名バージョン 4 リクエストを作成するには

  1. 署名バージョン 4 の正規リクエストを作成します。

    以下の JavaScript コードは正規リクエストを作成します。

    var datetime = AWS.util.date.iso8601(new Date()).replace(/[:\-]|\.\d{3}/g, ''); var date = datetime.substr(0, 8); var method = 'GET'; var protocol = 'wss'; var uri = '/mqtt'; var service = 'iotdevicegateway'; var algorithm = 'AWS4-HMAC-SHA256'; var credentialScope = date + '/' + region + '/' + service + '/' + 'aws4_request'; var canonicalQuerystring = 'X-Amz-Algorithm=' + algorithm; canonicalQuerystring += '&X-Amz-Credential=' + encodeURIComponent(credentials.accessKeyId + '/' + credentialScope); canonicalQuerystring += '&X-Amz-Date=' + datetime; canonicalQuerystring += '&X-Amz-SignedHeaders=host'; var canonicalHeaders = 'host:' + host + '\n'; var payloadHash = AWS.util.crypto.sha256('', 'hex') var canonicalRequest = method + '\n' + uri + '\n' + canonicalQuerystring + '\n' + canonicalHeaders + '\nhost\n' + payloadHash;
  2. 署名対象の文字列を作成し、署名キーを生成して、文字列に署名します。

    前の手順で作成した正規 URL から、署名対象の文字列を作成します。そのためには、ハッシュアルゴリズム、日付、認証情報の範囲、正規リクエストの SHA で構成される文字列を作成します。次に、以下の JavaScript コードに示しているように、署名キーを生成し、文字列に署名します。

    var stringToSign = algorithm + '\n' + datetime + '\n' + credentialScope + '\n' + AWS.util.crypto.sha256(canonicalRequest, 'hex'); var signingKey = SigV4Utils.getSignatureKey(credentials.secretAccessKey, date, region, service); var signature = AWS.util.crypto.hmac(signingKey, stringToSign, 'hex');
  3. 署名情報をリクエストに追加します。

    以下の JavaScript コードでは、クエリ文字列に署名情報を追加する方法を示しています。

    canonicalQuerystring += '&X-Amz-Signature=' + signature;
  4. STS サーバー、AssumeRole、または Amazon Cognito からのセッション認証情報がある場合は、署名後に URL 文字列の末尾にセッショントークンを追加します。

    canonicalQuerystring += '&X-Amz-Security-Token=' + encodeURIComponent(credentials.sessionToken);
  5. canonicalQuerystring に、プロトコル、ホスト、URI を付加します。

    var requestUrl = protocol + '://' + host + uri + '?' + canonicalQuerystring;
  6. WebSocket を開きます。

    以下の JavaScript コードでは、PAHO MQTT クライアントを作成し、AWS IoT への CONNECT を呼び出す方法を示しています。endpoint 引数は、AWS アカウント固有のエンドポイントです。clientId は、AWS アカウントに同時に接続するすべてのクライアント間で一意であるテキスト識別子です。

    var client = new Paho.MQTT.Client(requestUrl, clientId); var connectOptions = { onSuccess: function(){ // connect succeeded }, useSSL: true, timeout: 3, mqttVersion: 4, onFailure: function() { // connect failed } }; client.connect(connectOptions);

モバイルアプリケーションでの WebSocket プロトコルの使用

WebSocket による接続時に、AWS IoT Device SDK のいずれかを使用して、AWS IoT にデバイスを接続することをお勧めします。以下の AWS IoT Device SDK では、AWS IoT への WebSocket ベースの MQTT 接続がサポートされています。

MQTT over WebSocket プロトコルを使用して、AWS IoT にウェブアプリケーションを接続するためのリファレンス実装を見つけるには、「AWS ラボ WebSocket サンプル」を参照してください。

現在サポートされていないプログラミング言語やスクリプト言語を使用している場合、既存の WebSocket ライブラリを使用できますが、ただし、初期 WebSocket アップグレードリクエスト (HTTP POST) が署名バージョン 4 を使用して署名される場合に限ります。Eclipse Paho for JavaScript など一部の MQTT クライアントでは、ネイティブで WebSocket プロトコルがサポートされています。