将身份验证添加到Azure设备流

时间:2020-01-26 19:18:31

标签: azure azure-iot-hub

出于维护目的,我们希望使用IOT集线器并使用设备流来代理内部Web API。这工作得很好,但是我们还需要某种授权。为此目的,共享访问策略的粒度不够。

我宁愿使用某种身份验证令牌(JWT)来传递可以由设备本身检查的请求。如果令牌可以被验证并且使用具有适当的权利,则连接被接受,否则被拒绝。唯一可以配置的值是名称,因此我需要在名称中编码令牌。客户端代码可能如下所示:

客户代码

var deviceStreamRequest = new DeviceStreamRequest(streamName: "WebAPI?token=<JWT-token here>");
var result = await serviceClient.CreateStreamAsync(deviceId, deviceStreamRequest, cancellationToken).ConfigureAwait(false);

设备代码

var streamRequest = await deviceClient.WaitForDeviceStreamRequestAsync(cancellationToken).ConfigureAwait(false);
if (streamRequest != null)
{
   var token = GetTokenFromName(streamRequest.Name);
   if (!CheckClaim(token, "WebAPI"))
   {
       await deviceClient.RejectDeviceStreamRequestAsync(streamRequest, cancellationToken).ConfigureAwait(false);
       return;
   }

   await deviceClient.AcceptDeviceStreamRequestAsync(streamRequest, cancellationToken).ConfigureAwait(false);

   // ...
}

DeviceStreamRequest类确实包含一个AuthenticationToken,但它似乎是用于使用Websocket连接回IOT的身份验证令牌,不能用于其他目的。

我还有更好的方法来传递令牌,然后再使用名称吗?

1 个答案:

答案 0 :(得分:0)

Microsoft.Azure.Devices.DeviceStreamRequest 的当前版本不允许像设备直接方法中那样向设备填充请求有效负载。请求有效负载是向设备发送与流式预处理有关的附加(或业务)数据(例如B2B决策等)的最佳位置。

请注意,使用streamName传递令牌不是正确的方法,请参见.Net Reflector中的以下代码片段:

public override Task<DeviceStreamResponse> CreateStreamAsync(string deviceId, DeviceStreamRequest deviceStreamRequest, CancellationToken cancellationToken)
{
    return this.CreateStreamAsync(GetDeviceStreamUri(deviceId, deviceStreamRequest.StreamName), deviceStreamRequest, cancellationToken);
}

其中,GetDeviceStreamUri具有以下实现:

private static Uri GetDeviceStreamUri(string deviceId, string streamName)
{
    deviceId = WebUtility.UrlEncode(deviceId);
    object[] args = new object[] { deviceId, streamName };
    return new Uri("/twins/{0}/streams/{1}?api-version=2018-08-30-preview".FormatInvariant(args), UriKind.Relative);
}

如您所见,上面的Uri,已经有硬编码的查询参数,例如?api-version = 2018-08-30-preview

但是,基于使用底层通信(不使用SDK包)(例如REST API)的解决方案,您可以找到一种解决方法。请注意,此功能仍在预览中。

为了演示物联网设备流,我正在使用Azure IoT Hub Tester

以下屏幕片段显示了对IoT中心进行设备流传输的调用方POST请求:

enter image description here

如您所见, Microsoft.Azure.Devices.DeviceStreamRequest 只能处理流名称和两个标头,如 iothub-streaming-response-time-in-seconds em>和 iothub-streaming-connect-time-in-seconds

发布此请求,IoT中心将消息发送到设备。以下屏幕片段显示了我的虚拟MQTT设备1中收到的消息:

enter image description here

现在,device1可以评估消息有效负载,以决定是否接受 (代码202)或拒绝(代码4xx等)流传输过程。请注意,调用者调用存在一个响应时间限制(在我的示例中为15秒)。

一旦设备接受了此流传输过程,则调用者将收到IoT中心的响应,并在标头中包含详细信息,以从设备创建websocket通信和有效负载。以下是标题的示例:

    iothub-streaming-is-accepted: True
    iothub-streaming-url: wss://centralus.centralus-001.streams.azure-devices.net:443/bridges/ih/rk2019-iot/d/device1/sid/**** 
    iothub-streaming-auth-token: ***
    iothub-streaming-ip-address: 0.0.0.0

基于此,调用者可以在创建Websocket通信之前评估设备响应有效负载。