出于维护目的,我们希望使用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的身份验证令牌,不能用于其他目的。
我还有更好的方法来传递令牌,然后再使用名称吗?
答案 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请求:
如您所见, Microsoft.Azure.Devices.DeviceStreamRequest 只能处理流名称和两个标头,如 iothub-streaming-response-time-in-seconds em>和 iothub-streaming-connect-time-in-seconds 。
发布此请求,IoT中心将消息发送到设备。以下屏幕片段显示了我的虚拟MQTT设备1中收到的消息:
现在,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通信之前评估设备响应有效负载。