使用SAS令牌通过IoT Hub发送C2D消息时出现InvalidErrorCode

时间:2017-04-19 18:49:30

标签: azure-iot-hub azure-iot-sdk

我想将设备消息(C2D)发送到设备,这在IoTHub中已知。我在代码中使用SERVICE策略。从控制台应用程序(现在)或以后的WebApi发送。所以代码不会在设备上运行!

我想使用SAS令牌连接到期,而不是使用设备的对称密钥连接。我创建了以下代码:

辅助类:

..
using Microsoft.Azure.Devices;
using Microsoft.Azure.Devices.Common.Security;
..

public static class ServiceClientSasConnectionHelper
{
    public static string GetSasConnectionString(SasTokenModel sasTokenModel)
    {
        var sasToken = GetSasToken(sasTokenModel);
        var connectionString = string.Empty;
        if (!string.IsNullOrEmpty(sasTokenModel.PolicyName))
            connectionString = IotHubConnectionStringBuilder.Create(sasTokenModel.HostName, AuthenticationMethodFactory.CreateAuthenticationWithSharedAccessPolicyToken(sasTokenModel.PolicyName, sasToken)).ToString();
        else
            connectionString = $"HostName={sasTokenModel.HostName};DeviceId={sasTokenModel.DeviceId};SharedAccessSignature={sasToken}";
        return connectionString;
    }

    private static string GetSasToken(SasTokenModel sasTokenModel)
    {
        var sasBuilder = new SharedAccessSignatureBuilder
        {
            Key = sasTokenModel.SigninKey,
            Target = $"{sasTokenModel.HostName}/devices/{sasTokenModel.DeviceId}",
            TimeToLive = TimeSpan.FromMinutes(sasTokenModel.TokenLifeTimeInMinutes)
        };

        var sasToken = sasBuilder.ToSignature();

        if (!string.IsNullOrEmpty(sasTokenModel.PolicyName))
            sasToken += $"&skn={sasTokenModel.PolicyName}";

        return sasToken;
    }
}

从PROGRAM.CS调用:

var policyName = string.Empty;
policyName = ConfigHelper.GetPolicyName();  //service
var hostName = ConfigHelper.GetIotUri(); //companyname-Tenant2Display.azure-devices.net
var policyKey = ConfigHelper.GetPolicyKey(); // primarary key from Portal

var sasTokenModel = new SasTokenModel
{
    DeviceId = WebUtility.UrlEncode(deviceKeyPair.Id), //DeviceId
    SigninKey = string.IsNullOrEmpty(policyName) ? deviceKeyPair.Key : policyKey,
    HostName = hostName,
    PolicyName = policyName,
    TokenLifeTimeInMinutes = 5
};
var connString = ServiceClientSasConnectionHelper.GetSasConnectionString(sasTokenModel);
var serviceClient = ServiceClient.CreateFromConnectionString(connString);
await serviceClient.SendAsync(deviceId, commandMessage);

调用SendAsync时收到错误,并显示以下消息:

  

\ r \ nTracking   Id:fee6f860bdff42faa7cad8f81095223e-G:10-TimeStamp:04/19/2017 21:09:32

在属性Code的de exception中,值为:Microsoft.Azure.Devices.Common.Exceptions.ErrorCode.InvalidErrorCode

堆栈跟踪:

  

在   Microsoft.Azure.Devices.AmqpServiceClient.d__28.MoveNext()       ---从抛出异常的先前位置开始的堆栈跟踪结束---          在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务   任务)          在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)          在System.Runtime.CompilerServices.TaskAwaiter.GetResult()          在TelemetrySender.Service.Sender.d__1.MoveNext()   在C:\ repo \ TelemetrySender.cs:第34行

我在服务部分查看了Github存储库“azure-iot-sdk-csharp”,但我找不到此错误的原因。 我确实看到了错误信息的设置位置,但我不明白为什么。

任何可以帮助我的人?​​

1 个答案:

答案 0 :(得分:0)

  

我想将云设备消息(C2D)发送到设备......我想要   使用SAS令牌连接到期,而不是连接   使用设备的对称密钥

您无法使用设备级凭据发送Cloud-To-Device消息。您需要使用IoT中心级凭据。

因此,您需要删除/devices/{sasTokenModel.DeviceId} Target中的GetSasToken()。最后的SAS-token will have this format

SharedAccessSignature sig={signature-string}&se={expiry}&skn={policyName}&sr={URL-encoded-resourceURI}

我无法重现您的问题。我在桌面上测试,操作系统版本是10.0.14393。

但我可以使用您的完整代码和纠正SAS令牌格式(之前提到的)成功发送Cloud-To-Device消息。你可以参考一下。