[英]Generating an SAS Token in Java to download a file in an Azure Data Storage container
尝试生成SAS令牌以访问存储帐户中的某些文件。 我正在使用这里列出的方法:
https://docs.microsoft.com/zh-cn/rest/api/eventhub/generate-sas-token
现在,我的问题是,在我的一生中,我无法使sasToken字符串正常工作。 如果我通过门户网站(存储帐户中的共享访问签名)生成令牌,则可以通过带有提供的令牌的URL访问这些文件。
但是,我还不能使用上面链接的方法通过Java以编程方式生成SAS令牌。 我认为我的问题是正在加密的StringToSign。 在构造要加密的字符串时,我一直遵循以下示例:
https://docs.microsoft.com/zh-cn/rest/api/storageservices/constructing-an-account-sas
我所有的努力导致了以下结果之一:
<AuthenticationErrorDetail>Signature fields not well formed.</AuthenticationErrorDetail>
要么
<AuthenticationErrorDetail>Signature did not match. String to sign used was <insert string details here>
查看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%2Fzwis
看来我需要这样的字符串:
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;
其中accountName是来自Azure的存储帐户名称,而start / expiry是开始和到期字符串(即-2018-12-06T22:15:20Z),而azureApiVersion是“ 2017-11-09”。
然后,我尝试在像这样构造字符串之后返回令牌:
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");
我已经尝试过URL编码,而不是URL编码的开始/有效日期,以防万一。 我想念什么?
修复三点
getHMAC256
提到的getHMAC256方法问题
不要编码expiry
并以stringToSign
start
,否则签名将不匹配。 因为url中的编码部分将被Azure存储服务解码以计算预期的签名。
在stringToSign
,在azureApiVersion
之后错过一个\\n
。
这是完整的示例。
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;
}
我有一个更简单的方法
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);
您可以这样获得存储帐户:
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.