使用共享访问策略和密钥连接到使用 AMQP lite 的 IoT 中心

Connecting using shared access policy and key to IoT Hub using AMQP lite

按照 AMQP lite github 页面上的示例,我已使用 SASL ANONYMOUS 成功连接,然后在 $cbs 端点上标记。 (https://github.com/Azure/amqpnetlite/blob/master/docs/articles/service_to_iothub.md)

为每个请求生成 SAS 令牌是多余的,我想在连接到 IoT 中心时使用共享访问策略和密钥作为用户和密码。 我已按照 https://github.com/Azure/amqpnetlite/blob/master/docs/articles/building_application.md#specifying-an-address together with the indications on https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-security#protocol-specifics 上的文档进行操作,但我不断收到代码 "Sys" 的一些未经身份验证的错误。

凭据当然很好,因为我使用它们来生成 SAS 令牌,并且我尝试了用户名的变体(with/without 域)但没有成功。我专门检查过用户名和密码是否经过 URL 编码。

根据 SASL 标准的文档,错误代码 Sys 似乎表明接收器端存在一些问题(http://www.rfc-base.org/txt/rfc-3206.txt 第 3 页)。

还有其他人遇到过这个问题吗?有什么解决办法或者可以通过这种方式连接到IoT Hub吗?

谢谢, 乔治

由于没有发送 put-token 消息,我收到 "amqp:unauthorized-access" 错误:

        string sasToken = GetSharedAccessSignature(null, device_key, resourceUri, new TimeSpan(1, 0, 0));
        bool cbs = PutCbsToken(connection, host, sasToken, audience);

我在 Windows 10 桌面上使用以下代码进行测试,它适用于发送和接收:

    static string host = "[IOT_HUB_NAME].azure-devices.net";
    static int port = 5671;
    static string device_id = "[DEVICE_ID]";
    static string device_key = "[DEVICE_KEY]";
    static Session session;

    static void Main(string[] args)
    {
        Address address = new Address(host, port, null, null);
        Connection connection = new Connection(address);

        string audience = Fx.Format("{0}/devices/{1}", host, device_id);
        string resourceUri = Fx.Format("{0}/devices/{1}", host, device_id);

        string sasToken = GetSharedAccessSignature(null, device_key, resourceUri, new TimeSpan(1, 0, 0));
        bool cbs = PutCbsToken(connection, host, sasToken, audience);

        session = new Session(connection);

        SendEvent();
        ReceiveCommands();
        Console.ReadLine();
    }

    static private void SendEvent()
    {
        string entity = Fx.Format("/devices/{0}/messages/events", device_id);

        SenderLink senderLink = new SenderLink(session, "sender-link", entity);

        var messageValue = Encoding.UTF8.GetBytes("i am a message.");
        Message message = new Message()
        {
            BodySection = new Data() { Binary = messageValue }
        };

        senderLink.Send(message);
        senderLink.Close();
    }

    static private void ReceiveCommands()
    {
        string entity = Fx.Format("/devices/{0}/messages/deviceBound", device_id);

        ReceiverLink receiveLink = new ReceiverLink(session, "receive-link", entity);

        Message received = receiveLink.Receive();
        if (received != null)
            receiveLink.Accept(received);
        Console.WriteLine(received.BodySection.ToString());
        receiveLink.Close();
    }

更多信息请参考“CONNECTING TO THE AZURE IOT HUB USING AN AMQP STACK”。

更新:

下面的代码使用共享访问策略和密钥(SASL PLAIN),而不是像上面的代码一样使用 SAS 令牌:

    static string host = "[IOT_HUB_NAME].azure-devices.net";
    static int port = 5671;
    static string device_id = "[DEVICE_ID]";
    static string device_key = "[DEVICE_KEY]";
    private const string username_hublevel = "iothubowner@sas.root.[IOT_HUB_NAME]";
    private const string password_hublevel = "SharedAccessSignature sr={URL-encoded-resourceURI}&sig={signature-string}&se={expiry}&skn={policyName}";

    static Session session;

    static void Main(string[] args)
    {
        Address address = new Address(host, port, username_hublevel, password_hublevel);
        Connection connection = new Connection(address);

        string audience = Fx.Format("{0}/devices/{1}", host, device_id);
        string resourceUri = Fx.Format("{0}/devices/{1}", host, device_id);

        session = new Session(connection);

        SendEvent();
        Console.WriteLine("Sent Hello AMQP!");
        ReceiveCommands();
        Console.ReadLine();
    }