[英]Generating an SAS Token in Java to download a file in an Azure Data Storage container
Trying to generate an SAS Token to access certain files in a Storage Account. 尝试生成SAS令牌以访问存储帐户中的某些文件。 I'm using the methods listed here:
我正在使用这里列出的方法:
https://docs.microsoft.com/en-us/rest/api/eventhub/generate-sas-token https://docs.microsoft.com/zh-cn/rest/api/eventhub/generate-sas-token
Now, the problem I have is I cannot, for the life of me, make the sasToken string work. 现在,我的问题是,在我的一生中,我无法使sasToken字符串正常工作。 If I generate the token via the Portal (Shared Access Signature in the Storage Account), I can access those files via a URL with the provided Token.
如果我通过门户网站(存储帐户中的共享访问签名)生成令牌,则可以通过带有提供的令牌的URL访问这些文件。
However I have yet to be able to generate an SAS token programmatically via Java using the methods I linked above. 但是,我还不能使用上面链接的方法通过Java以编程方式生成SAS令牌。 I think my problem is the StringToSign that is being encrypted.
我认为我的问题是正在加密的StringToSign。 I've been following this example when constructing the string to encrypt:
在构造要加密的字符串时,我一直遵循以下示例:
https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-an-account-sas https://docs.microsoft.com/zh-cn/rest/api/storageservices/constructing-an-account-sas
All my efforts have resulted in either: 我所有的努力导致了以下结果之一:
<AuthenticationErrorDetail>Signature fields not well formed.</AuthenticationErrorDetail>
or 要么
<AuthenticationErrorDetail>Signature did not match. String to sign used was <insert string details here>
Looking at the Portal generated sasToken that works for me: 查看Portal生成的sasToken对我有用:
?sv=2017-11-09&ss=f&srt=o&sp=r&se=2018-12-06T22:15:20Z&st=2018-12-06T14:15:20Z&spr=https&sig=%2Bi1TWv5D80U%2BoaIeoBh1wjaO1p4xVFx4nRZt%2FzwiszY%3D ?sv = 2017-11-09&ss = f&srt = o&sp = r&se = 2018-12-06T22:15:20Z&st = 2018-12-06T14:15:20Z&spr = https&sig =%2Bi1TWv5D80U%2BoaIeoBh1wjaO1p4xVFx4nRZt%2Fzwis
It seems I need a String like so: 看来我需要这样的字符串:
String stringToSign = accountName + "\n" +
"r\n" +
"f\n" +
"o\n" +
URLEncoder.encode(start, "UTF-8") + "\n" +
URLEncoder.encode(expiry, "UTF-8") + "\n" +
"\n" +
"https\n" +
azureApiVersion;
Where accountName is the storage account name from Azure, and start/expiry are the start and expiry strings (ie- 2018-12-06T22:15:20Z) and azureApiVersion is "2017-11-09". 其中accountName是来自Azure的存储帐户名称,而start / expiry是开始和到期字符串(即-2018-12-06T22:15:20Z),而azureApiVersion是“ 2017-11-09”。
I then try to return the token after constructing the string like so: 然后,我尝试在像这样构造字符串之后返回令牌:
String signature = getHMAC256(key, stringToSign);
sasToken = "sv=" + azureApiVersion +
"&ss=f" +
"&srt=o" +
"&sp=r" +
"&se=" +URLEncoder.encode(expiry, "UTF-8") +
"&st=" + URLEncoder.encode(start, "UTF-8") +
"&spr=https" +
"&sig=" + URLEncoder.encode(signature, "UTF-8");
I've tried URL encoding and not URL encoding the the start/expiry dates as well, just in case that was messing things up. 我已经尝试过URL编码,而不是URL编码的开始/有效日期,以防万一。 What am I missing?
我想念什么?
Three points to fix 修复三点
getHMAC256
method problem as mentioned by @Gaurav getHMAC256
提到的getHMAC256方法问题
Don't encode expiry
and start
in stringToSign
or the signature won't match. 不要编码
expiry
并以stringToSign
start
,否则签名将不匹配。 Because the encoded part in url will be decoded by Azure Storage Service to calculate the expected signature. 因为url中的编码部分将被Azure存储服务解码以计算预期的签名。
In stringToSign
, miss one \\n
after azureApiVersion
. 在
stringToSign
,在azureApiVersion
之后错过一个\\n
。
Here's the complete sample. 这是完整的示例。
public static void GetFileSAS(){
String accountName = "accountName";
String key = "accountKey";
String resourceUrl = "https://"+accountName+".file.core.windows.net/fileShare/fileName";
String start = "startTime";
String expiry = "expiry";
String azureApiVersion = "2017-11-09";
String stringToSign = accountName + "\n" +
"r\n" +
"f\n" +
"o\n" +
start + "\n" +
expiry + "\n" +
"\n" +
"https\n" +
azureApiVersion+"\n";
String signature = getHMAC256(key, stringToSign);
try{
String sasToken = "sv=" + azureApiVersion +
"&ss=f" +
"&srt=o" +
"&sp=r" +
"&se=" +URLEncoder.encode(expiry, "UTF-8") +
"&st=" + URLEncoder.encode(start, "UTF-8") +
"&spr=https" +
"&sig=" + URLEncoder.encode(signature, "UTF-8");
System.out.println(resourceUrl+"?"+sasToken);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
private static String getHMAC256(String accountKey, String signStr) {
String signature = null;
try {
SecretKeySpec secretKey = new SecretKeySpec(Base64.getDecoder().decode(accountKey), "HmacSHA256");
Mac sha256HMAC = Mac.getInstance("HmacSHA256");
sha256HMAC.init(secretKey);
signature = Base64.getEncoder().encodeToString(sha256HMAC.doFinal(signStr.getBytes("UTF-8")));
} catch (Exception e) {
e.printStackTrace();
}
return signature;
}
I got a simpler method 我有一个更简单的方法
SharedAccessAccountPolicy sharedAccessAccountPolicy = new SharedAccessAccountPolicy();
sharedAccessAccountPolicy.setPermissionsFromString("racwdlup");
long date = new Date().getTime();
long expiryDate = new Date(date + 8640000).getTime();
sharedAccessAccountPolicy.setSharedAccessStartTime(new Date(date));
sharedAccessAccountPolicy.setSharedAccessExpiryTime(new Date(expiryDate));
sharedAccessAccountPolicy.setResourceTypeFromString("sco");
sharedAccessAccountPolicy.setServiceFromString("bfqt");
String sasToken = "?" + storageAccount.generateSharedAccessSignature(sharedAccessAccountPolicy);
You can get the storage account like this: 您可以这样获得存储帐户:
private String storageConnectionString = "DefaultEndpointsProtocol=https;AccountName=<storage name>;AccountKey=<your key>;EndpointSuffix=core.windows.net";
storageAccount = CloudStorageAccount.parse(storageConnectionString);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.