1

一段时间以来,我一直在尝试从 Android 手机创建一个 IoT Hub 设备,尽管遵循了我能找到的所有说明或教程,但我仍然得到:

{
"Message": "ErrorCode:IotHubUnauthorizedAccess;Unauthorized",
"ExceptionMessage": "Tracking ID:cc3e0c722b6040f89239c14c8bace4b9-G:0-TimeStamp:12/09/2021 23:29:46"

}

我已经尝试在 Android 代码中以几种不同的方式在 Java 中创建 SharedAccessSignature:

    private static String GetSASToken(String resourceUri, String keyName, String key)
{
    long epoch = System.currentTimeMillis()/1000L;
    int week = 60*60*24*7;
    String expiry = Long.toString(epoch + week);
    Log.d(TAG, "GetSASToken: expiry: " + expiry);

    String sasToken = null;
    try {
        String stringToSign = URLEncoder.encode(resourceUri, "UTF-8") + "\n" + expiry;
        String signature = getHMAC256(key, stringToSign);
        sasToken = "SharedAccessSignature sr=" + URLEncoder.encode(resourceUri, "UTF-8") +"&sig=" +
                URLEncoder.encode(signature, "UTF-8") + "&se=" + expiry + "&skn=" + keyName;
    } catch (UnsupportedEncodingException e) {

        e.printStackTrace();
    }

    return sasToken;
}

public static String generateSasToken(String resourceUri, String key) throws Exception {
    // Token will expire in one hour
    long expiry = Instant.now().getEpochSecond() + 3600;

    String stringToSign = URLEncoder.encode(resourceUri, "UTF-8") + "\n" + expiry;

    byte[] decodedKey = Base64.getDecoder().decode(key);

    Mac sha256HMAC = Mac.getInstance("HmacSHA256");
    SecretKeySpec secretKey = new SecretKeySpec(decodedKey, "HmacSHA256");
    sha256HMAC.init(secretKey);
    Base64.Encoder encoder = Base64.getEncoder();

    String signature = new String(encoder.encode(
            sha256HMAC.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8))), StandardCharsets.UTF_8);

    String token = "SharedAccessSignature sr=" + URLEncoder.encode(resourceUri, "UTF-8")
            + "&sig=" + URLEncoder.encode(signature, StandardCharsets.UTF_8.name()) + "&se=" + expiry;

    return token;
}

然后调用通常的方式:

            try{
            URL finalURL = new URL(stringUrl);

            urlConnection = (HttpsURLConnection)finalURL.openConnection();
            urlConnection.setReadTimeout(10000);
            urlConnection.setConnectTimeout(0);
            urlConnection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
            urlConnection.setRequestProperty("Accept","application/json");
            urlConnection.setRequestProperty("Authorization",token2);
            urlConnection.setRequestMethod("PUT");
            urlConnection.setDoInput(true);
            urlConnection.setDoOutput(true);
            int responseCode = urlConnection.getResponseCode();
        }catch (MalformedURLException e) {
            e.printStackTrace();
            Log.d(TAG, "doInBackground: error 1 " + e.toString());
        }catch(UnknownHostException e){
            Log.d(TAG, "doInBackground: e: " + e);
        }
        catch(Exception e){
            Log.d(TAG, "doInBackground: error 2 " + e.toString());
        }
        finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }
        return null;
    }

我的 Sas 令牌采用以下形式:

SharedAccessSignature sr=XXXXXXXXXXXXXXXX.azure-devices.net&sig=XXXXXXXXXXXXXXXXXXXXXXXB6%2BM6L0JR0UpgFxmvuX7g%3D&se=1639698883&skn=iothubowner

我在 Postman 中使用的 URL 是:

https://XXXXXXXXXX-westus2.azure-devices.net/devices/testDevice1?api-version=2020-03-13

将 Authorization 标头设置为上述 SAS

我还使用 Python 来创建 SAS,以防编码出现问题。但是我所做的一切都是在点击同样的未经授权的访问消息,我开始把头发拉出来。

4

1 回答 1

0

以下屏幕片段显示了使用 REST POST调用将遥测数据发送到 IoT 中心的示例:

在此处输入图像描述

出于测试目的,使用包含的Azure IoT Explorer也生成 SaS 令牌,请参阅以下屏幕片段:

在此处输入图像描述

更新:

以下屏幕片段显示了使用 REST PUT 请求创建 Azure IoT 中心设备的示例:

在此处输入图像描述

上述请求的 sasToken 是由文档中描述的 C# 代码根据 IoT Hub 共享访问策略iothubowner 生成的:

string sasToken = generateSasToken("rk2019-iot.azure-devices.net", "****", "iothubowner");
于 2021-12-10T13:44:47.323 回答