How to call REST API for azure file storage using

2019-04-02 19:48发布

问题:

I want to call REST API related to file storage of azure through postman. Here is how I am making my request :

I am making request to list all shares in file storage account as described here : https://docs.microsoft.com/en-us/rest/api/storageservices/list-shares

I am getting below error:

"The Date header in the request is incorrect." What changes I should make ?

Edit1 :

When I provided date n correct format, I have error like this :

I am getting below error: "The MAC signature found in the HTTP request '' is not the same as any computed signature. Server used following string to sign: 'GET"

How to resolve this?

回答1:

With your updated screenshot, it seems like that your problem is no longer related to x-ms-date. The reason for this 403 error is the Authorization attribute in the Header which format as

Authorization="[SharedKey|SharedKeyLite] [AccountName]:[Signature]"

You should't directly use the Access Key on Azure Portal as the Signature part of Authorization,instead it should be constructed encoding request string by using the HMAC-SHA256 algorithm over the UTF-8-encoded. format as

Signature=Base64(HMAC-SHA256(UTF8(StringToSign)))

which mentioned on the official document.

Sample java code as below show you how to construct Signature part of Authorization:

String stringToSign = "GET\n" 
       + "\n" // content encoding
       + "\n" // content language
       + "\n" // content length
       + "\n" // content md5
       + "\n" // content type
       + "\n" // date
       + "\n" // if modified since
       + "\n" // if match
       + "\n" // if none match
       + "\n" // if unmodified since
       + "\n" // range
       + "x-ms-date:" + date + "\nx-ms-version:2015-02-21\n" // headers
       + "/" + <your account name> + "/"+"\ncomp:list"; // resources
       String auth = getAuthenticationString(stringToSign);

private static String getAuthenticationString(String stringToSign) throws Exception {
       Mac mac = Mac.getInstance("HmacSHA256");
       mac.init(new SecretKeySpec(Base64.decode(key), "HmacSHA256"));
       String authKey = new String(Base64.encode(mac.doFinal(stringToSign.getBytes("UTF-8"))));
       String auth = "SharedKey " + account + ":" + authKey;
       return auth;
}

The auth parameter in the code is generated your Signature mentioned above,then you could fill it in the Authorization property and re-send request in Postman.

The screenshot as below:

Important notice:

In the above code,you should't miss "\ ncomp: list" in the //resources line,otherwise it will also return 403 error. You could find the rules in the Constructing the Canonicalized Resource String.



回答2:

The link you point towards holds this example:

PUT http://myaccount/mycontainer?restype=container&timeout=30 HTTP/1.1  
x-ms-version: 2015-02-21  
x-ms-date: Fri, 26 Jun 2015 23:39:12 GMT  
Authorization: SharedKey myaccount:ctzMq410TV3wS7upTBcunJTDLEJwMAZuFPfr0mrrA08=  
Content-Length: 0  

The date format you're using is not correct:

All authenticated requests must include the Coordinated Universal Time (UTC) timestamp for the request. You can specify the timestamp either in the x-ms-date header, or in the standard HTTP/HTTPS Date header. If both headers are specified on the request, the value of x-ms-date is used as the request's time of creation.

EDIT:
On the authorization header, the Authentication for the Azure Storage Services link in the article in your link states the following:

To authenticate a request, you must sign the request with the key for the account that is making the request and pass that signature as part of the request.

The format for the Authorization header is as follows:
Authorization="[SharedKey|SharedKeyLite] :"
where SharedKey or SharedKeyLite is the name of the authorization scheme, AccountName is the name of the account requesting the resource, and Signature is a Hash-based Message Authentication Code (HMAC) constructed from the request and computed by using the SHA256 algorithm, and then encoded by using Base64 encoding.

Here's some more info on the Hash-based Message Authentication Code (HMAC)

Since you commented:

Hi, key is the same as provided in 'Access-keys' tab of my account of azure portal. What's your suggestion?

That's where the problem is. You shouldn't use the key as the Signature for the message, you need to calculate the Signature based on the key.

In short:

  • Calculate the SHA256 hash of your request using the key from the 'Access-keys' tab
  • Base64 encode the SHA256 hash output
  • Use the Base64 encoded string as the Signature