AWS IoT:在浏览器中订阅主题

8
我正在使用AWS开发Serverless应用程序。
我想使用纯JavaScript(无Node.js,React,Angular等)订阅主题。
IoT和IoTData SDK不支持“订阅主题”功能。
为了实现这一点,我需要通过`require('aws-iot-device')`实现`aws-iot-device` sdk(但我无法在纯JS中使用它)。
不幸的是,该SDK仅适用于像Node.js或Browserify之类的运行时。 那么,有没有办法将SDK实现到纯JS中,并从浏览器订阅主题?
提前致谢。
2个回答

7
这是如何做到的,完全正常运作:
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.11.2/moment.min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/core-min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/hmac-min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/sha256-min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.min.js" type="text/javascript"></script>

将这些库复制到您的HTML中。
 function SigV4Utils(){}

      SigV4Utils.sign = function(key, msg) {
          var hash = CryptoJS.HmacSHA256(msg, key);
          return hash.toString(CryptoJS.enc.Hex);
        };

        SigV4Utils.sha256 = function(msg) {
          var hash = CryptoJS.SHA256(msg);
          return hash.toString(CryptoJS.enc.Hex);
        };

        SigV4Utils.getSignatureKey = function(key, dateStamp, regionName, serviceName) {
          var kDate = CryptoJS.HmacSHA256(dateStamp, 'AWS4' + key);
          var kRegion = CryptoJS.HmacSHA256(regionName, kDate);
          var kService = CryptoJS.HmacSHA256(serviceName, kRegion);
          var kSigning = CryptoJS.HmacSHA256('aws4_request', kService);
          return kSigning;
        };

        function createEndpoint(regionName, awsIotEndpoint, accessKey, secretKey) {
          var time = moment.utc();
          var dateStamp = time.format('YYYYMMDD');
          var amzdate = dateStamp + 'T' + time.format('HHmmss') + 'Z';
          var service = 'iotdevicegateway';
          var region = regionName;
          var secretKey = secretKey;
          var accessKey = accessKey;
          var algorithm = 'AWS4-HMAC-SHA256';
          var method = 'GET';
          var canonicalUri = '/mqtt';
          var host = awsIotEndpoint;
          var credentialScope = dateStamp + '/' + region + '/' + service + '/' + 'aws4_request';
          var canonicalQuerystring = 'X-Amz-Algorithm=AWS4-HMAC-SHA256';
          canonicalQuerystring += '&X-Amz-Credential=' + encodeURIComponent(accessKey + '/' + credentialScope);
          canonicalQuerystring += '&X-Amz-Date=' + amzdate;
          canonicalQuerystring += '&X-Amz-SignedHeaders=host';
          var canonicalHeaders = 'host:' + host + '\n';
          var payloadHash = SigV4Utils.sha256('');
          var canonicalRequest = method + '\n' + canonicalUri + '\n' + canonicalQuerystring + '\n' + canonicalHeaders + '\nhost\n' + payloadHash;
          var stringToSign = algorithm + '\n' +  amzdate + '\n' +  credentialScope + '\n' +  SigV4Utils.sha256(canonicalRequest);
          var signingKey = SigV4Utils.getSignatureKey(secretKey, dateStamp, region, service);
          var signature = SigV4Utils.sign(signingKey, stringToSign);
          canonicalQuerystring += '&X-Amz-Signature=' + signature;
          canonicalQuerystring += '&X-Amz-Security-Token=' + encodeURIComponent(AWS.config.credentials.sessionToken);
          return 'wss://' + host + canonicalUri + '?' + canonicalQuerystring;
        }
        var endpoint = createEndpoint(
        'eu-central-1',  // YOUR REGION
        'xxxxxx.iot.eu-central-1.amazonaws.com', // YOUR IoT ENDPOINT  
        accesskey, // YOUR ACCESS KEY    
        secretkey); // YOUR SECRET ACCESS KEY   

        var clientId = Math.random().toString(36).substring(7);
        var client = new Paho.MQTT.Client(endpoint, clientId);
        var connectOptions = {
          useSSL: true,
          timeout: 3,
          mqttVersion: 4,
          onSuccess: subscribe
        };
        client.connect(connectOptions);
        client.onMessageArrived = onMessage;
        client.onConnectionLost = function(e) {
           console.log(e) 
        };


        function subscribe() {
         client.subscribe("my/things/something");
         console.log("subscribed");
        }

        function onMessage(message) {
          var status = JSON.parse(message.payloadString);
        }

使用此代码,您可以在纯客户端JavaScript中订阅IoT主题。不需要Node.js、React.js或类似的工具!


2
这是很多代码和(可以说)敏感信息在客户端,我会将签名代码移到服务器端并查询 API 端点,返回已签名的 URL。实际上,这也是我所做的。 - Solo
1
这行代码需要一个名为session_token的变量。它从哪里来?canonicalQuerystring += '&X-Amz-Security-Token=' + encodeURIComponent(session_token); return 'wss://' + host + canonicalUri + '?' + canonicalQuerystring; - Marc
嘿,我们已将该行更改为 canonicalQuerystring += '&X-Amz-Security-Token=' + encodeURIComponent(AWS.config.credentials.sessionToken);如果您包含了正确的 AWS 库,您应该可以默认调用 AWS.config.credentials.sessionToken。抱歉回答晚了……因为假期 :D - David

1
你可以在浏览器中使用 paho js 或者 mqttjs。aws-iot-device sdk for javascript 是对 mqttjs 的封装。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接