Azure blob storage java generate SAS token always throw sr is mandatory. Cannot be empty error
Asked Answered
M

1

1

I want to use Java to generate a SAS token, this is what I do:

 public static String GetSASToken(String resourceUri, String keyName, String key) {
        long epoch = System.currentTimeMillis() / 1000L;
        int week = 60 * 30 * 1000;
        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;
    }

This code is nothing but copied from microsoft website,

Then in main class:

  String key = "xxxxxHh9jP1ZOTYZI/z1OCVeThsjK00sSc3TYUuiHJQ==";
        String kn = "frankbucket";
        String url = "https://frankbucket.blob.core.windows.net/mycontainer";
        System.out.print(AzureSASTokenGenerator.GetSASToken(url, kn, key));

when I run this, I got below SAS:

SharedAccessSignature sr=https%3A%2F%2Ffrankbucket.blob.core.windows.net%2Fmycontainer&sig=xxxj7Fgbkz5OSag%2BzFQAzBkIdd3I1J9AmFwxjcQg%3D&se=1588299503&skn=frankbucket

In Javascript:

var blobUri = 'https://frankbucket.blob.core.windows.net';
    var token =
        "SharedAccessSignature sr=https%3A%2F%2Ffrankbucket.blob.core.windows.net%2Fmycontainer&sig=ZA5fgKKny5%2BzdffvdEmy6WdsqqpoMsssssYYM9ruXgAdo0%3D&se=1588299257&skn=frankbucket";
    var blobService = AzureStorage.Blob.createBlobServiceWithSas(blobUri, token);

    blobService.listBlobsSegmented('mycontainer', null, function(error, results) {

When I run it, I got below error:

<?xml version="1.0" encoding="utf-8"?><Error><Code>AuthenticationFailed</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.

RequestId:ea315aac-001e-00a0-0700-0f2e4d000000 Time:2020-04-10T06:22:18.2383162Zsr is mandatory. Cannot be empty

I have no clue where is the issue, I got code form microsoft website, but it does not work.

Can anyone show me working example for this?

Hope to hear your advice.

Thanks

Margretmargreta answered 10/4, 2020 at 6:25 Comment(5)
Could you tell me which type of SAS token you want to create? Account or service?Withy
There are so many issues with your code unfortunately. For starters, you're missing permissions from your SAS. You mentioned that you copied the code from a Microsoft site. Can you share the link for that?Hornsby
Also, why are you not using SDK methods to generate the Shared Access Signature?Hornsby
Thanks for replying, this is the doc i am following: learn.microsoft.com/en-us/rest/api/eventhub/generate-sas-token I just want to be able to do file operation in storage account/containers Also, what SDK method I can use? I am very new to Azure, can anyone share link to me? ThanksMargretmargreta
Please check your local PC time Zone and SDK version. Similar issue in GitHub could be helpful github.com/Azure/azure-storage-node/issues/330Natie
W
2

If you want to know how to create account sas token with java, please refer to the following code

  public void callblobRestAPIWithSas() throws NoSuchAlgorithmException, InvalidKeyException, IOException {
 // 1. create account sas token
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
        fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.add(Calendar.DATE, -2);
        String start = fmt.format(cal.getTime());
        cal.add(Calendar.DATE, 4);
        String expiry =  fmt.format(cal.getTime());
        String StorageAccountName = "blobstorage0516";
        String StorageAccountKey = "";
        String apiVersion="2019-07-07";
        String  resource ="sco";
        String permissions ="rwdlac";
        String service = "b";
        String stringToSign = StorageAccountName + "\n" +
                permissions +"\n" +  // signed permissions
                service+"\n" + // signed service
                resource+"\n" + // signed resource type
                start + "\n" + // signed start
                expiry + "\n" + // signed expiry
                "\n" +  // signed IP
                "https\n" + // signed Protocol
                apiVersion+"\n"; // signed version

        SecretKeySpec secretKey = new SecretKeySpec(Base64.getDecoder().decode(StorageAccountKey), "HmacSHA256");
        Mac sha256HMAC = Mac.getInstance("HmacSHA256");
        sha256HMAC.init(secretKey);
        String signature=Base64.getEncoder().encodeToString(sha256HMAC.doFinal(stringToSign.getBytes("UTF-8")));
        String sasToken = "sv=" + apiVersion +
                "&ss=" + service+
                "&srt=" + resource+
                "&sp=" +permissions+
                "&se=" + URLEncoder.encode(expiry, "UTF-8") +
                "&st=" + URLEncoder.encode(start, "UTF-8") +
                "&spr=https" +
                "&sig=" + URLEncoder.encode(signature,"UTF-8");
        //2. test the sas token
       String resourceUrl="https://blobstorage0516.blob.core.windows.net/test/help.txt"; // your blob url
        URL url = new URL(resourceUrl+"?"+sasToken);
        OkHttpClient httpClient =  new OkHttpClient().newBuilder().build();
        Request request = new Request.Builder()
                .url(url)
                .method("GET", null)
                .build();

        okhttp3.Response response = httpClient.newCall(request).execute();
        if(response.isSuccessful()){
            System.out.println("The blob content : "+ response.body().string());

        }
}

enter image description here

Withy answered 13/4, 2020 at 1:55 Comment(1)
Thanks Jim, this is the only working code that I have upto now.Margretmargreta

© 2022 - 2024 — McMap. All rights reserved.