简体   繁体   English

在Java中生成SAS令牌以下载Azure数据存储容器中的文件

[英]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 修复三点

  1. getHMAC256 method problem as mentioned by @Gaurav getHMAC256提到的getHMAC256方法问题

  2. 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存储服务解码以计算预期的签名。

  3. 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.

相关问题 生成SAS以进行Azure存储访问 - Generating SAS for Azure storage access 如何在Java中基于SAS令牌访问Azure WASB容器? - How to Access Azure WASB Container Based on SAS Token in Java? 如何生成 SAS 令牌并使用它将文件上传到 Azure Blob 存储? - How to generate a SAS token and use it to upload a file to Azure Blob Storage? 使用Java在android中使用sas url将文件上传到azure存储 - Upload file into azure storage using sas url in android using Java 为 Java 中的文件生成 Azure SAS 令牌:签名字段格式不正确 - Generate Azure SAS Token for File in Java: Signature fields not well formed 带有SAS令牌的Java Azure SB连接 - Java Azure SB Connection with SAS token Azure 文件共享 SAS 令牌签名未按预期生成,如何为文件对象生成签名以匹配门户中生成的签名? - Azure File share SAS token signature not generating as expected, How do one generate signature for file object to match the one generated in portal? 仅使用 SAS 令牌连接到 Azure 存储帐户? - Connect to Azure Storage Account using only SAS token? 如何在 Java 中计算 Azure 存储容器大小? - How to compute Azure Storage Container Size in Java? 如何在Java中为Azure的文件服务添加SAS? - How to add SAS for file services of azure in java?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM