REST API Azure 事件中心 ExpiredToken
REST API Azure Event Hub ExpiredToken
我正在使用 Rest 工具 Chrome 客户端测试 API 以验证我提出的 POST 请求是否正确,以便在 Java 应用。我的请求格式如下:
POST /androidhub/publishers/android/messages?timeout=60&api-version=2014-01
HTTP/1.1 HOST: androidhub-124.servicebus.windows.net
authorization: SharedAccessSignature sr=androidhub-124.servicebus.windows.net&sig=mykeySAS=&se=146480684&skn=RootManageSharedAccessKey
content-type: application/json, application/atom+xml;type=entry;charset=utf-8
content-length: 45 { "DeviceId":"dev-01", "Temperature":"37.0" }
但是我有以下错误。
<Error>
<Code>401</Code>
<Detail>ExpiredToken: . TrackingId:2f6d284e-d7d2-4c9c-81a5-79c542ce8eee_G7, SystemTracker:androidhub-124.servicebus.windows.net:androidhub/publishers/android/messages, Timestamp:5/25/2016 7:13:33 PM</Detail>
</Error>
密钥在我使用之前被重新生成了。我如何在不设置密钥过期时间的情况下不收到该错误或发出请求?
谢谢
根据我的经验,如果 se
值 146480684
在这里是正确的 post,我认为问题是由 expiry
时间引起的,因为 se
键,以当前时间和 1970 年 1 月 1 日午夜 UTC 之间的秒数为单位。
所以 expiry
时间作为 se
键的值应该使用下面的 Java 代码得到。
long now = System.currentTimeMillis();
int expiry = (int)(now/1000) + 3600;
作为参考,你可以参考C#的官方文档,请看https://msdn.microsoft.com/en-us/library/azure/mt652140.aspx。
除了设置正确的 se
值外,您还必须确保 sig
是经过加密签名(使用 HMAC 256)的 base64 字符串,其中包含命名空间(在您的情况下androidhub-124
) 和 se
,使用 SAS 密钥进行签名。
在 java 中生成 sig
的示例代码由 Microsoft here:
提供
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=" + 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 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;
}
我正在使用 Rest 工具 Chrome 客户端测试 API 以验证我提出的 POST 请求是否正确,以便在 Java 应用。我的请求格式如下:
POST /androidhub/publishers/android/messages?timeout=60&api-version=2014-01
HTTP/1.1 HOST: androidhub-124.servicebus.windows.net
authorization: SharedAccessSignature sr=androidhub-124.servicebus.windows.net&sig=mykeySAS=&se=146480684&skn=RootManageSharedAccessKey
content-type: application/json, application/atom+xml;type=entry;charset=utf-8
content-length: 45 { "DeviceId":"dev-01", "Temperature":"37.0" }
但是我有以下错误。
<Error>
<Code>401</Code>
<Detail>ExpiredToken: . TrackingId:2f6d284e-d7d2-4c9c-81a5-79c542ce8eee_G7, SystemTracker:androidhub-124.servicebus.windows.net:androidhub/publishers/android/messages, Timestamp:5/25/2016 7:13:33 PM</Detail>
</Error>
密钥在我使用之前被重新生成了。我如何在不设置密钥过期时间的情况下不收到该错误或发出请求?
谢谢
根据我的经验,如果 se
值 146480684
在这里是正确的 post,我认为问题是由 expiry
时间引起的,因为 se
键,以当前时间和 1970 年 1 月 1 日午夜 UTC 之间的秒数为单位。
所以 expiry
时间作为 se
键的值应该使用下面的 Java 代码得到。
long now = System.currentTimeMillis();
int expiry = (int)(now/1000) + 3600;
作为参考,你可以参考C#的官方文档,请看https://msdn.microsoft.com/en-us/library/azure/mt652140.aspx。
除了设置正确的 se
值外,您还必须确保 sig
是经过加密签名(使用 HMAC 256)的 base64 字符串,其中包含命名空间(在您的情况下androidhub-124
) 和 se
,使用 SAS 密钥进行签名。
在 java 中生成 sig
的示例代码由 Microsoft here:
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=" + 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 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;
}