问题
Trying to generate Azure SAS token in order to be able to use Service Bus REST Api.
Found this link:
http://blog.simontimms.com/2015/01/30/sending-message-to-azure-service-bus-using-rest/
How to achieve the same on Android?
My Current attempt looks like this:
private String generateSasToken(String uri, String keyName, String key){
String ret = "";
long tokenExpirationTime = (System.currentTimeMillis() / 1000) + (10 * 365 * 24 * 60 * 60);
try {
String stringToSign = new URL(uri).toString() + "\n" + tokenExpirationTime;
SecretKey secretKey = null;
byte[] keyBytes = key.getBytes("UTF-8");
Mac mac = Mac.getInstance("HMACSHA256");
secretKey = new SecretKeySpec(keyBytes, mac.getAlgorithm());
mac.init(secretKey);
String signature = Base64.encodeToString(mac.doFinal(stringToSign.getBytes("UTF-8")), Base64.DEFAULT);
ret = String.format("SharedAccessSignature sr=%s&sig=%s&se=%s&skn=%s",
URLEncoder.encode(uri),
URLEncoder.encode(signature),
String.valueOf(tokenExpirationTime),
keyName);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return ret;
}
After calling the Rest API of service bus using Postman i get the following :
401 40103: Invalid authorization token signature Time 261 ms
Update: Found this link
https://azure.microsoft.com/en-us/documentation/articles/notification-hubs-android-get-started/
Under section 6 the code for android
回答1:
I have no Android environment to test, I have a similar scenario in only java environment, it works fine, the following is my code:
private static String generateSasToken(String uri, String keyName, String key){
String ret = "";
// long tokenExpirationTime = (System.currentTimeMillis() / 1000) + (10 * 365 * 24 * 60 * 60);
Date now = new Date();
Date previousDate=new Date(1970);
long tokenExpirationTime = ((now.getTime() - previousDate.getTime()) / 1000 )+3600;
try {
String stringToSign = URLEncoder.encode(new URL(uri).toString(),java.nio.charset.StandardCharsets.UTF_8.toString()) + "\n" + tokenExpirationTime;
System.out.println(stringToSign);
SecretKey secretKey = null;
byte[] keyBytes = key.getBytes("UTF-8");
Mac mac = Mac.getInstance("HMACSHA256");
secretKey = new SecretKeySpec(keyBytes, mac.getAlgorithm());
mac.init(secretKey);
byte[] digest = mac.doFinal(stringToSign.getBytes());
//We then use the composite signing key to create an oauth_signature from the signature base string
String signature = Base64.encodeBase64String(digest);
System.out.println( URLEncoder.encode(signature, java.nio.charset.StandardCharsets.UTF_8.toString()));
// String signature = Base64.encodeBase64String(mac.doFinal(stringToSign.getBytes("UTF-8")));
ret = String.format("SharedAccessSignature sr=%s&sig=%s&se=%s&skn=%s",
URLEncoder.encode(uri, java.nio.charset.StandardCharsets.UTF_8.toString()),
URLEncoder.encode(signature, java.nio.charset.StandardCharsets.UTF_8.toString()),
String.valueOf(tokenExpirationTime),
keyName);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return ret;
}
I have changed two places, 1) the tokenExpirationTime 2) URLEncoder.encode the String stringTosign, please try with my suggestion, hope this could give you some tips.
回答2:
I don't know if this helps you, but here is an example in C#:
class Program
{
static void Main(string[] args)
{
var sasToken = createToken("yournamespace.servicebus.windows.net”,
"device_send_listen", "xxxxxxx");
}
private static string createToken(string resourceUri, string keyName, string key)
{
TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
var expiry = Convert.ToString((int)sinceEpoch.TotalSeconds + 3600); //EXPIRES in 1h
string stringToSign = HttpUtility.UrlEncode(resourceUri) + "\n" + expiry;
HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
var sasToken = String.Format(CultureInfo.InvariantCulture,
"SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",
HttpUtility.UrlEncode(resourceUri), HttpUtility.UrlEncode(signature), expiry, keyName);
return sasToken;
}
}
来源:https://stackoverflow.com/questions/31180367/generate-azure-sas-token-on-android