0

我正在尝试使用 azure IoT Hub 文档中给出的代码片段生成 SAS 令牌,以在 IoT 中心调用 GET 设备 API(https://iot-hub-name.azure-devices.net/devices?api-版本=2020-03-13)。代码是

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);

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

            e.printStackTrace();
        }

        return sasToken;
    }


  public static String getHMAC256(String key, String input) {
      Mac sha256_HMAC = null;
      String hash = null;
      try {
          sha256_HMAC = Mac.getInstance("HmacSHA256");
          SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(), "HmacSHA256");
          sha256_HMAC.init(secret_key);
          Encoder encoder = Base64.getEncoder();

          hash = new String(encoder.encode(sha256_HMAC.doFinal(input.getBytes("UTF-8"))));

      } catch (InvalidKeyException e) {
          e.printStackTrace();
      } catch (NoSuchAlgorithmException e) {
          e.printStackTrace();
      } catch (IllegalStateException e) {
          e.printStackTrace();
      } catch (UnsupportedEncodingException e) {
          e.printStackTrace();
      }

      return hash;
  }

然后我将生成 SAS 令牌方法称为,

String sasToken= GetSASToken("https://<iot-hub-name>.azure-devices.net", "shared access policy name", "primary key of the shared access policy");

但是生成的 SAS 令牌给出了 401 Unauthorized,这意味着生成的令牌不正确。谁能帮我解决这个问题?

4

1 回答 1

0

我认为您正在使用本文档中的代码?虽然 IoT 中心确实公开了 EventHub,但这不是调用 API 的正确 SAS 令牌。

您可以使用Java SDK来生成您的令牌。如果您坚持自己编写代码,则此类包含您要查找的代码。该类将从服务连接字符串中检索您需要的值,但您可以轻松地将其省略。连接字符串仅具有您还具有的值:

HostName=<hub-name>;SharedAccessKeyName=<policy-name>;SharedAccessKey=<access-key>

我链接的类从该字符串中提取值并在方法中使用它们private String buildToken(),该方法包含您正在重新实现的代码。

另请注意,在您https://<iot-hub-name>.azure-devices.net用作资源名称的问题中,对于此令牌(就像在连接字符串中一样),您可以省略https://

要完成我的回答,您可以将构造函数更改为此,您将获得令牌:

public IotHubServiceSasToken(String hubName, String keyValue, String keyName)
    {            
        this.resourceUri = hubName;
        this.keyValue = keyValue;
        this.keyName = keyName;
        this.expiryTime = buildExpiresOn();
        this.token =  buildToken();
    }
于 2020-07-22T16:06:52.827 回答