咱们想象这么一个IoT应用场景:厂商A使用AWS IoT来开发物联网解决方案,那么A把设备卖给用户的时候,须要使用户可以登入AWS IoT系统来控制其购买的A的设备,也就是说给用户分配适当的权限。下面本文简要归纳讨论如何实现这样一个场景。javascript
部分细节能够参考这个博客:https://blog.csdn.net/luo_bo1/article/details/84567988html
1. 用户身份的管理java
首先,用户必须有一个独特的身份在这个系统中。事实上,开发者甚至不须要本身维护一个管理身份的服务器,用户也不肯意注册那么多帐号。为解决这个问题,便产生了直接使用第三方帐号身份来映射到AWS IoT系统中的方法,也就是说,用户只要有一些公共的第三方身份提供商的帐号(如谷歌、亚马逊等),便容许直接使用AWS IoT系统。本文使用了Login with Amazon这个第三方服务,厂商只要根据Login with Amazon的文档实现一个接口便可。主要有以下几步:web
(1) 在developer.amazon.com后台注册一个OAuth的客户端,还要提供隐私策略,得到一个亚马逊发放的OAuth ClietID和Client Secret,这样亚马逊才能认证这是哪一个开发者想得到用户的信息。在用户受权后,便可向亚马逊得到用户的基自己份信息。api
(2)本人是用Web实现的,所以须要设置OAuth过程当中须要的回调URL,而且把这个URL加入Login with Amazon的白名单。此外,还要在Web setting中设置Allow origin。在调用亚马逊这个接口时,亚马逊会验证ClientId,web URL来认证开发者的身份,而且有了origin也能防止这是别人在冒用你的ClientID(用户点击login with amazon的时候浏览器会携带origin发给亚马逊,尽管这个有时能够伪造);用户受权后,结果token会以重定向的方式让用户浏览器访问白名单中存在的回调URL,这样就确保只有开发者的服务器能够得到token,防止别人偷取。浏览器
(3)开发者得到了用户的token,就能够查询得到用户在Amazon的 信息,进而得到到一个惟一的用户ID。这个ID应该是惟一匿名化的身份标识,即不会泄露用户的信息,不一样Client得到的也不同,防止用户被追踪。安全
2. 给对应用户分配适当的权限服务器
如今咱们得到了用户的身份,可是用户要访问的是AWS IoT中的资源,如何设置才能将AWS中的权限,关联至第三方身份提供商给的身份呢?这就须要AWS Cognito的Identity Pool出马了。websocket
(1)首先,cognito须要验证用户的身份,而后在Identity Pool中建立一个对应的身份映射。这首先须要在cognito的Identity Pool中设置Authentication providers,添加开发者建立的login with amazon的标识,即session
(2)开发者得到用户第三方token后,向cognito发送该token,就代表了该用户身份,cognito会再返回给程序一系列cognito的token。因为用户cognito就是AWS本身的服务,因此能够关联AWS IoT中的权限给该用户使用。具体动态关联的方法没有深究,只是用aws cli简单测试实现,正确动态作法能够参考官方PPT:https://www.slideshare.net/AmazonWebServices/iot-apps-with-aws-iot-and-websockets
aws cli使用须要先设置, 能够参考https://razeencheng.com/post/tool-awscli-overview-1
指令有点坑,记录一下:
aws iot attach-policy --policy-name <value> --target <value>
(3)最后强调一点,策略设置时要注意权限的控制,AWS提供了策略变量来得到用户特有的不变凭证,参考https://blog.csdn.net/luo_bo1/article/details/84567988便可。另外设置的时候有点坑,既要设置认证过cognito用户的粗粒度权限,又要在AWS IoT中设置细粒度的权限而且关联到cognito用户上。
3.附录JS代码
注:必须本身搭建个web服务器来测试,不然因为浏览器安全限制(好像是专门本地的文件)没法使用亚马逊的js API。推荐XAMPP,起名成html直接放到htdoc下就行了,xampp还直接支持https。
1 <!doctype html> 2 <html lang="en_US"> 3 4 <head> 5 <script src="https://sdk.amazonaws.com/js/aws-sdk-2.451.0.min.js"></script> 6 </head> 7 8 <body> 9 <a href id="LoginWithAmazon"> 10 <img border="0" alt="Login with Amazon" 11 src="https://images-na.ssl-images-amazon.com/images/G/01/lwa/btnLWA_gold_156x32.png" width="156" 12 height="32" /> 13 </a> 14 <button onclick="myFunction()">Myfunction</button> 15 16 <div id="amazon-root"></div> 17 <script type="text/javascript"> 18 19 window.onAmazonLoginReady = function () { 20 amazon.Login.setClientId('amzn1.application-oa2-client.XXXXX'); 21 }; 22 (function (d) { 23 var a = d.createElement('script'); a.type = 'text/javascript'; 24 a.async = true; a.id = 'amazon-login-sdk'; 25 a.src = 'https://assets.loginwithamazon.com/sdk/na/login1.js'; 26 d.getElementById('amazon-root').appendChild(a); 27 })(document); 28 </script> 29 30 <script type="text/javascript"> 31 document.getElementById('LoginWithAmazon').onclick = function () { 32 options = { scope: 'profile' }; 33 amazon.Login.authorize(options, 34 'https://127.0.0.1/test.html'); 35 return false; 36 }; 37 </script> 38 39 <script> 40 function myFunction() { 41 // Set the region where your identity pool exists (us-east-1, eu-west-1) 42 AWS.config.region = 'us-east-1'; 43 44 // Configure the credentials provider to use your identity pool 45 AWS.config.credentials = new AWS.CognitoIdentityCredentials({ 46 IdentityPoolId: 'us-east-1:d9fe3941-df89-4190-ab80-XXXXX', 47 Logins: { // optional tokens, used for authenticated login 48 'www.amazon.com': '第三方登录得到的token' 49 } 50 }); 51 //检查得到的用户token是否有效https://api.amazon.com/auth/O2/tokeninfo?access_token=Atza%7CIwEBINapjp9vq3UgptE95f5fqL4DQ5K57Ex5tWTLh0D6K3-omYt8N2H_D-H8tDnn9fyqkrbZ0HdrnQJ4F2_-VtMVB5IOM5quEqr8qZCVVOswPKBHYnL5VwZ4YXtWJiqkssPlsvygcSD74lJWJlAVGTewHP9HWAR4HL4kADPJIyKxI2i_BWpGrDpQb6nw5Yeh6VbtTG9zTWpZUfZsENpkoMo6K5m0H-rw_NmiiZxIBsaOgtIlYTTcG5qKcRFevPXk8SQ8BZKRmXd5Hx2M1bld4rInXLfR41OvuTXH1GKXJHVKMc2hvGt6sMOCcqAXw2ABKAciYAQ1X9uV-RD5zWcp02bw7fgKr8IgwmORyHUhLnnwY8FRYTUQQcTlNHsHVzsbSQ7FYZn7IST9O7nKiSyUryh3VJyCnEqyyvpDzIhSjNjPIyIprpKZoZL1iVKH0oLL_4slT79DVAmuOsUjUKjXnWHbImrF0ZZissrfHPCE2708RWwu-ZgpSsmhPqgRpgE-TlX803ziNo2kvazKpdPg6O6MGG7H2yV8PUW-zwVXO1XxJTK4Nw 52 53 // Make the call to obtain credentials 54 AWS.config.credentials.get(function () { 55 // Credentials will be available when this function is called. 56 var accessKeyId = AWS.config.credentials.accessKeyId; 57 var secretAccessKey = AWS.config.credentials.secretAccessKey; 58 var sessionToken = AWS.config.credentials.sessionToken; 59 var identityId = AWS.config.credentials.identityId; 60 console.log(accessKeyId); 61 console.log(secretAccessKey); 62 console.log(sessionToken); 63 console.log(identityId); 64 65 }); 66 } 67 </script> 68 69 70 </html>