【问题标题】:How to use AWS IoT to send/receive messages to/from Web Browser如何使用 AWS IoT 向/从 Web 浏览器发送/接收消息
【发布时间】:2016-05-28 03:44:52
【问题描述】:

我们正在尝试使用亚马逊网络服务物联网 (AWS IoT) 从/向网络浏览器发送消息(例如:。鉴于 AWS IoT 支持 JavaScript,我们预计这是可能 ...

我们在 AWS IoT 文档中进行了搜索,但只找到了服务器端示例(暴露了 AWS 机密/密钥...)

是否有任何很好的工作示例或教程用于使用 AWS IoT 在浏览器中通过 WebSockets/MQTT 发送/接收消息(例如:使用 AWS Cognito 进行身份验证)?谢谢!

【问题讨论】:

    标签: node.js amazon-web-services websocket amazon-cognito aws-iot


    【解决方案1】:

    这是一个使用 JS 中的 cognito 身份池来连接、发布和响应订阅的示例。

    // Configure Cognito identity pool
    AWS.config.region = 'us-east-1';
    var credentials = new AWS.CognitoIdentityCredentials({
        IdentityPoolId: 'us-east-1:your identity pool guid',
    });
    
    // Getting AWS creds from Cognito is async, so we need to drive the rest of the mqtt client initialization in a callback
    credentials.get(function(err) {
        if(err) {
            console.log(err);
            return;
        }
        var requestUrl = SigV4Utils.getSignedUrl('wss', 'data.iot.us-east-1.amazonaws.com', '/mqtt',
            'iotdevicegateway', 'us-east-1',
            credentials.accessKeyId, credentials.secretAccessKey, credentials.sessionToken);
        initClient(requestUrl);
    });
    
    function init() {
      // do setup stuff
    }
    
    // Connect the client, subscribe to the drawing topic, and publish a "hey I connected" message
    function initClient(requestUrl) {
        var clientId = String(Math.random()).replace('.', '');
        var client = new Paho.MQTT.Client(requestUrl, clientId);
        var connectOptions = {
            onSuccess: function () {
                console.log('connected');
    
                // subscribe to the drawing
                client.subscribe("your/mqtt/topic");
    
                // publish a lifecycle event
                message = new Paho.MQTT.Message('{"id":"' + credentials.identityId + '"}');
                message.destinationName = 'your/mqtt/topic';
                console.log(message);
                client.send(message);
            },
            useSSL: true,
            timeout: 3,
            mqttVersion: 4,
            onFailure: function () {
                console.error('connect failed');
            }
        };
        client.connect(connectOptions);
    
        client.onMessageArrived = function (message) {
    
            try {
                console.log("msg arrived: " +  message.payloadString);
            } catch (e) {
                console.log("error! " + e);
            }
    
        };
    }
    

    Documentation for the credentials.get call, here

    请记住授权您的 IAM 角色进行订阅/发布。这是一个示例:

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "iot:Connect"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": "iot:Receive",
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": "iot:Subscribe",
                "Resource": [
                    "arn:aws:iot:us-east-1::your/mqtt/topic"
                ]
            },
            {
                "Effect": "Allow",
                "Action": "iot:Publish",
                "Resource": [
                    "arn:aws:iot:us-east-1::your/mqtt/topic"
                ]
            }
        ]
    }
    

    【讨论】:

    • sigv4函数为here供参考。
    • 收到以下错误:aws-sdk-2.7.1.js:6834 Uncaught Error: moment is not defined(...)callListeners @ aws-sdk-2.7.1.js:6834emit @ aws -sdk-2.7.1.js:6810emit @ aws-sdk-2.7.1.js:4054transition @ aws-sdk-2.7.1.js:3831runTo @ aws-sdk-..... 因为我已经更新了 aws sdk 也是,但仍然遇到同样的错误,你能帮我吗,或者如果可能的话,分享你正在使用的 aws-sdk.js 文件。
    • 您使用过“iotdevicegateway”,您将什么作为参数传递为“iotdevicegateway”?我们必须传递 resourceId 还是 DeviceId?
    • 只需为您的应用添加时刻:npm i moment --save。 'iotdevicegateway' 也保持字符串格式。
    • 只是出于好奇,您需要使用this 之类的东西吗?我在代码中看到new Paho.MQTT.Client,但我看不出它来自哪里
    【解决方案2】:

    如果其他人正在寻找解决方案:here's a tutorial,它通过一个简单的聊天应用程序演示如何使用 AWS IOT 上的无服务器和 Websockets 将实时更新到 ReactJS 前端。教程源代码可在on Github获取。

    【讨论】:

    • 此示例不包括 Cognito 支持。不清楚:该示例是否在 javascript 源代码中公开了键?
    【解决方案3】:

    很难找到在浏览器中集成 AWS IoT 的好教程。

    基本上您需要一些身份验证方法(Facebook、Google、AWS Cognito、您自己的支持 SAML 的 SSO 服务),然后您需要执行以下步骤:

    1. 使用您的身份验证方法配置 Cognito 用户池或联合身份池。
    2. 在浏览器中,您必须实现扩展流 (https://aws.amazon.com/blogs/mobile/understanding-amazon-cognito-authentication-part-4-enhanced-flow/)
    3. 您需要在 IoT 中为您用户的 Cognito identityId AttachPolicy - 它将用作主体(与设备使用证书的方式相同)。
    4. 您需要使用 https://github.com/aws/aws-iot-device-sdk-js 创建 MQTT 客户端,并提供从扩展流身份验证收到的临时 accessKeyIdsecretKeysessionToken

    【讨论】:

      【解决方案4】:

      在这里了解IAM 策略和AWS IOT 策略之间的区别非常重要。假设您使用cognito user pool 作为您的身份提供者。

      首先,您需要设置一个cognito identity pool,将身份池链接到您的user pool 并将一个角色(将IAM 策略附加到此角色)到此身份池。

      其次,在您的应用程序中,您首先登录以获得用户池凭据,然后调用

          AWS.config.credentials = new AWS.CognitoIdentityCredentials({
            IdentityPoolId: 'us-west-2:b8d2b32b-cbab-4ae3-9d47-1624d09c9350',
            Logins: {
              'cognito-idp.us-west-2.amazonaws.com/${userPoolIdentity}': userPoolCredential.getIdToken().getJwtToken(),
            }
          });
      

      用 aws 临时访问凭证交换您的用户池凭证:

          AWS.config.getCredentials(e => {
            if(e) console.log("Get credential failed", e);
            this.device = AwsIot.device({//AwsIot is the aws-iot-sdk package
              clientId: clientID,//clientId is just random string
              host: '*-ats.iot.us-west-2.amazonaws.com',//replace * with your own host
              protocol: 'wss',
              accessKeyId: AWS.config.credentials.accessKeyId,
              secretKey: AWS.config.credentials.secretAccessKey,
              sessionToken: AWS.config.credentials.sessionToken
            });
            this.device.on('connect', function() {
              console.log("DEVICE CONNECTED");
            });
            this.device.subscribe('test');
            this.device
            .on('message', function(topic, payload) {
              console.log(`TOPIC IS ${topic}\nMESSAGE IS ${payload.toString()}`);
            });
          });
      

      但是上面的代码不行!!! 这是棘手的部分:通过交换用户池凭据获得的凭据只是一个临时凭据,代表您刚刚附加到身份池的 AWS IAM 策略!当它请求与您的 IOT 连接时,AWS 将检查是否允许请求以及是否允许执行用户请求的操作。您已经获得了IAM 策略,因此您可以请求,但它会检查附加到此身份的AWS IOT 策略。由于您还没有这样做,因此您不能做您真正要求的事情(即连接)。所以在你第一次想连接的时候,你应该给这个身份附加一个IOT策略。您可以通过命令行或

        (<AWS.CognitoIdentityCredentials>AWS.config.credentials).refresh(e => {
          if(e) console.log('error', e);
          const principal = (<AWS.CognitoIdentityCredentials>AWS.config.credentials).identityId;
          console.log(`IdentityId: ${principal}`);
          this.attachPrincipalPolicy("test-delete-after-use", principal);
        });
        attachPrincipalPolicy(policyName, principal) {
          new AWS.Iot().attachPrincipalPolicy({ 
            policyName: policyName, // you need to create policy beforehand in iot
            principal: principal 
          }, err => {
            err ? console.log('ATTACH PRINCIPAL POLICY ERROR', err) : console.log('ATTACH PRINCIPAL POLICY SUCCESS');
          });
        }
      

      现在,当身份尝试与 IOT 连接时,IOT 将找到附加到此身份的 IOT 策略,并批准此连接。

      很抱歉措辞不好。综上所述,您需要明确IAM 策略和IOT 策略之间的区别。这只是我的理解,它可能有错误的地方。如果你找到它,请发表评论或编辑我的答案。

      重要 刚刚从官方文档中找到了这两个政策之间的关系: https://docs.aws.amazon.com/iot/latest/developerguide/pub-sub-policy.html 查看 HTTP 和 WebSocket 客户端策略

      部分

      【讨论】:

      • 如果可能的话,我真的很想看看你的完整解决方案?!这正是我目前面临的问题。
      • @AshkanHovold 它是怎么回事?你解决了那个场景吗?我面临同样的事情,我正在寻找更多信息,因为我发现 AWS 文档很难遵循......
      猜你喜欢
      • 2019-05-01
      • 2015-04-07
      • 2019-04-24
      • 2013-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-15
      • 2016-02-21
      相关资源
      最近更新 更多