zoukankan      html  css  js  c++  java
  • Azure IoT Hub 入门

    最初开始接触Azure IoT Hub的时候,被各种connection string和endpoint弄的眼花缭乱。本入门系列旨在将Azure IoT Hub 权限管理机制以及各个接口(endpoint)的用途解释清楚。

    首先抛出一个典型的IoT解决方案的架构,以让读者对IoT有个大概的认识。该架构通过平台层的核心服务和应用层组件来实现典型IoT解决方案需要解决的三个主要问题:

    • 设备的连接;
    • 数据的处理、分析与管理;
    • 数据的有效呈现以及业务逻辑的处理。

    回到本文的主题:IoT Hub 权限管理以及Endpoint。

      1. Azure IoT Hub 权限管理
        总结起来,Azure 提供了以下两种权限管理机制:
        • Hub 层面的共享访问策略(shared access policies)
          在portal上新创建的IoT Hub默认包含了以下策略,你可以对已有的策略进行修改,或者添加新的策略。
          • iothubowner: 拥有所有的权限
          • service: ServiceConnect 权限 (给予服务端通信监控接口访问权限,例如读取device-to-cloud的消息,发送cloud-to-device消息等)
          • device: DeviceConnect 权限(给予设备端的通信接口访问权限,例如发送device-to-cloud消息)
          • registryRead: RegistryRead 权限(读设备注册列表)
          • registryReadWrite: RegistryRead和RegistryWrite权限(读写设备注册列表)  
        • device 层面的安全令牌(security credentials)
          IoT Hub维护了一个所有设备的注册列表。列表里的每一个设备都有自己的symmetric key,用户可以根据这个symmetric key 来获得DeviceConnect的权限。 
        针对特定场景下所需要的权限举例如下:
        * 设备管理组件:registryReadWrite 策略
        * 事物处理组件:service 策略
        * 单设备连接组件:device策略
    1. 如何生成安全令牌
      为避免直接在网络上传输密钥,IoT Hub通过安全令牌来对设备以及云端服务进行授权。一般情况下,Azure IoT Hub SDKs会自动根据密钥生成安全令牌。但在某些情况下(例如直接使用MQTT,AMQP或者HTTP接口)需要客户自己去生成安全令牌。
      安全令牌的格式如下:
      SharedAccessSignature sig={signature-string}&se={expiry}&skn={policyName}&sr={URL-encoded-resourceURI}

      针对每个字段的注解,请参考:https://azure.microsoft.com/en-us/documentation/articles/iot-hub-devguide-security/
      下面给出完整的C#实现:

      public class SharedAccessSignatureBuilder
          {
              private string key;
      
              public string Key
              {
                  get
                  {
                      return this.key;
                  }
                  set
                  {
                      // StringValidationHelper.EnsureBase64String(value, "Key");
                      this.key = value;
                  }
              }
      
              public string KeyName
              {
                  get;
                  set;
              }
      
              public string Target
              {
                  get;
                  set;
              }
      
              public TimeSpan TimeToLive
              {
                  get;
                  set;
              }
      
              public string TargetService
              {
                  get;
                  set;
              }
      
              public SharedAccessSignatureBuilder()
              {
                  this.TimeToLive = TimeSpan.FromMinutes(20);
                  TargetService = "iothub";
              }
      
              private static string BuildExpiresOn(TimeSpan timeToLive)
              {
                  DateTime dateTime = DateTime.UtcNow.Add(timeToLive);
                  TimeSpan timeSpan = dateTime.Subtract(SharedAccessSignatureConstants.EpochTime);
                  return Convert.ToString(Convert.ToInt64(timeSpan.TotalSeconds, CultureInfo.InvariantCulture), CultureInfo.InvariantCulture);
              }
      
              private static string BuildSignature(string keyName, string key, string target, TimeSpan timeToLive, string targetService = "iothub")
              {
                  string str = SharedAccessSignatureBuilder.BuildExpiresOn(timeToLive);
                  string str1 = WebUtility.UrlEncode(target);
                  List<string> strs = new List<string>()
                  {
                      str1,
                      str
                  };
                  string str2 = SharedAccessSignatureBuilder.Sign(string.Join("
      ", strs), key, targetService);
                  StringBuilder stringBuilder = new StringBuilder();
                  stringBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0} {1}={2}&{3}={4}&{5}={6}", new object[] { "SharedAccessSignature", "sr", str1, "sig", WebUtility.UrlEncode(str2), "se", WebUtility.UrlEncode(str) });
                  if (!string.IsNullOrEmpty(keyName))
                  {
                      stringBuilder.AppendFormat(CultureInfo.InvariantCulture, "&{0}={1}", new object[] { "skn", WebUtility.UrlEncode(keyName) });
                  }
                  return stringBuilder.ToString();
              }
      
              private static string Sign(string requestString, string key, string targetService)
              {
                  string base64String;
      
                  if (!string.IsNullOrEmpty(targetService) && targetService.ToLower() == "servicebus")
                  {
                      using (HMACSHA256 hMACSHA256 = new HMACSHA256(Encoding.UTF8.GetBytes(key))) // key is not decoded
                      {
                          base64String = Convert.ToBase64String(hMACSHA256.ComputeHash(Encoding.UTF8.GetBytes(requestString)));
                      }
                  }
                  else
                  {
                      using (HMACSHA256 hMACSHA256 = new HMACSHA256(Convert.FromBase64String(key))) // key is decoded
                      {
                          base64String = Convert.ToBase64String(hMACSHA256.ComputeHash(Encoding.UTF8.GetBytes(requestString)));
                      }
                  }
      
                  return base64String;
              }
      
              public string ToSignature()
              {
                  return SharedAccessSignatureBuilder.BuildSignature(this.KeyName, this.Key, this.Target, this.TimeToLive, this.TargetService);
              }
          }
      SharedAccessSignatureBuilder
      public class SharedAccessSignatureConstants
          {
              public const int MaxKeyNameLength = 256;
      
              public const int MaxKeyLength = 256;
      
              public const string SharedAccessSignature = "SharedAccessSignature";
      
              public const string AudienceFieldName = "sr";
      
              public const string SignatureFieldName = "sig";
      
              public const string KeyNameFieldName = "skn";
      
              public const string ExpiryFieldName = "se";
      
              public const string SignedResourceFullFieldName = "SharedAccessSignature sr";
      
              public const string KeyValueSeparator = "=";
      
              public const string PairSeparator = "&";
      
              public readonly static DateTime EpochTime;
      
              public readonly static TimeSpan MaxClockSkew;
      
              static SharedAccessSignatureConstants()
              {
                  SharedAccessSignatureConstants.EpochTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
                  SharedAccessSignatureConstants.MaxClockSkew = TimeSpan.FromMinutes(5);
              }
          }
      SharedAccessSignatureConstants

      你也可以直接引用我编译的DLL 文件,并在项目中引用它。 

      using SharedAccessSignatureGenerator;

      调用方式:

      1)根据IoT Hub 共享访问策略生成安全令牌
      假设IoT Hub 共享访问策略连接串如下:

      HostName=<iot-hub-name>.azure-devices.cn;SharedAccessKeyName=<policy name>;SharedAccessKey=<key>

      调用方法:

      var sasBuilder = new SharedAccessSignatureBuilder()
                      {
                          KeyName = <policy name>,
                          Key = <key>,
                          Target = string.Format("{0}/devices", <iot-hub-name>),
                          TimeToLive = TimeSpan.FromDays(Convert.ToDouble(ttlValue))
                      };
      string sas = sasBuilder.ToSignature();

      输出示例:

      SharedAccessSignature sr=devpod.azure-devices.cn%2Fdevices&sig=eAtQg7Du%2FUBrBk9zELLpOwELyGSVuOH0qHv1iJ63xnc%3D&se=1478756374&skn=iothubowner

      2)根据设备的symmetric key生成安全令牌

      假设IoT Hub 设备的链接串如下:

      HostName=<iot-hub-name>.azure-devices.cn;DeviceId=<deviceId>;SharedAccessKey=<key>

      调用方法:

      var sasBuilder = new SharedAccessSignatureBuilder()
                      {
                          Key = <key>,
                          Target = string.Format("{0}/devices/{1}", <iot-hub-name>, WebUtility.UrlEncode(<deviceId>)),
                          TimeToLive = TimeSpan.FromDays(Convert.ToDouble(ttlValue))
                      };
      string sas = sasBuilder.ToSignature();

      输出示例:

      SharedAccessSignature sr=devpod.azure-devices.cn%2Fdevices%2Fdevice001&sig=x6rceLUBASP99GU03LAX5w0YQ8gF05J6%2BYX5gJwKISQ%3D&se=1478756286

        

  • 相关阅读:
    css布局
    常用正则表达式
    读书笔记Hadoop实战1
    C++ IDE for Linux
    由计算机的锁是怎么实现的
    pthread
    转:C++反汇编揭秘2 – VC编译器的运行时错误检查(RTC)
    PyDev Python 开发的IDE
    转:C++反汇编揭秘1 一个简单的C++程序反汇编解析
    如何查找命令对应的软件包
  • 原文地址:https://www.cnblogs.com/xingzhou/p/6046639.html
Copyright © 2011-2022 走看看