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

        

  • 相关阅读:
    1026 Table Tennis (30)
    1029 Median
    1025 PAT Ranking (25)
    1017 Queueing at Bank (25)
    1014 Waiting in Line (30)
    1057 Stack (30)
    1010 Radix (25)
    1008 Elevator (20)
    字母大小写转换
    Nmap的基础知识
  • 原文地址:https://www.cnblogs.com/xingzhou/p/6046639.html
Copyright © 2011-2022 走看看