AWS IoT
开发人员指南
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

基于 WebSocket 的 MQTT 协议

AWS IoT 支持基于 WebSocket 的 MQTT 协议,从而使基于浏览器的远程应用程序能够通过连接到 AWS IoT 的设备使用 AWS 凭证发送和接收数据。指定 AWS 凭证时使用的是 AWS 签名版本 4。WebSocket 支持服务适用于 TCP 端口 443,因此,消息可以穿过大多数防火墙和 Web 代理。

通过发送 HTTP GET 请求在客户端上启动 WebSocket 连接。您使用的 URL 应采用以下格式:

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

指定 WebSocket 协议。

endpoint

特定于您的 AWS 账户的 AWS IoT 终端节点。您可以使用 AWS IoT CLI describe-endpoint 命令找到该终端节点。

region

您的 AWS 账户所在的 AWS 区域。

mqtt

指定您使用 WebSocket 协议发送 MQTT 消息。

当服务器进行响应时,客户端将发送升级请求,向服务器表明它将使用 WebSocket 协议进行通信。在服务器确认升级请求后,将使用 WebSocket 协议执行所有通信。您使用的 WebSocket 实施将充当传输协议。您使用 WebSocket 协议发送的数据是 MQTT 消息。

在 Web 应用程序中使用 WebSocket 协议

大多数 Web 浏览器提供的 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 前面加上协议、主机和 URL:

    var requestUrl = protocol + '://' + host + uri + '?' + canonicalQuerystring;
  6. 打开 WebSocket。

    以下 JavaScript 代码将表明如何创建 Paho MQTT 客户端并将 CONNECT 调用到 AWS IoT 中。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 设备开发工具包将您的设备连接到 AWS IoT。以下 AWS IoT 设备开发工具包支持利用基于 WebSocket 的 MQTT 连接到 AWS IoT:

有关使用基于 WebSocket 的 MQTT 协议将 Web 应用程序连接到 AWS IoT 的参考实施案例,请参阅 AWS 实验室 WebSocket 示例

如果您使用的是当前不受支持的编程或脚本语言,则只要使用签名版本 4 为初始 WebSocket 升级请求 (HTTP POST) 签名,便可以使用任何现有的 WebSocket 库。有些 MQTT 客户端(如 Eclipse Paho for JavaScript)可为 WebSocket 协议提供本机支持。