简体   繁体   中英

Creating a Directory in azure storage with REST API

I'm trying to create a directory using REST API. Below is the code for Signature. Can you help me to find the issue in the code:

string storageKey = 'storage key';
string storageName = '<storageName>';
Datetime dt = Datetime.now();
string formattedDate = dt.formatGMT('EEE, dd MMM yyyy HH:mm:ss')+ ' GMT';
system.debug('formattedDate--'+formattedDate);

string CanonicalizedHeaders = 'x-ms-date:'+formattedDate+'\nx-ms-version:2016-05-31';
string CanonicalizedResource = '/' + storageName + '/<myShareName>/<DirectoryName>\nrestype:directory';
string StringToSign = 'PUT\n\n\n\n\napplication/xml;charset=utf-8\n\n\n\n\n\n\n' + CanonicalizedHeaders+'\n'+CanonicalizedResource;
system.debug('StringToSign--'+StringToSign);

Blob temp = EncodingUtil.base64Decode(storageKey);
Blob hmac = Crypto.generateMac('HmacSHA256',Blob.valueOf(StringToSign),temp ); //StringToSign
system.debug('oo-'+EncodingUtil.base64Encode(hmac));
HttpRequest req = new HttpRequest();
req.setMethod('PUT');
req.setHeader('content-type', 'application/xml;charset=utf-8');
req.setHeader('content-length', '0');
req.setHeader('x-ms-version','2016-05-31' );
req.setHeader('x-ms-date', formattedDate);
string signature = EncodingUtil.base64Encode(hmac);
string authHeader =  'SharedKey <storageName>'+':'+signature;

req.setHeader('Authorization',authHeader);
req.setEndpoint('https://<storageName>.file.core.windows.net/<myShareName>/<DirectoryName>&restype=directory');

Http http = new Http();
HTTPResponse res= http.send(req);                

Refer the link for azure documentation: https://docs.microsoft.com/en-us/rest/api/storageservices/create-directory

I wrote the following java code for your reference, and it works well for me.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import com.microsoft.windowsazure.core.utils.Base64;

public class CreateDirectory {

    private static final String account = "jaygong";
    private static final String key = "******";

    public static void main(String args[]) throws Exception {
        System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
        String urlString = "http://" + account + ".file.core.windows.net/testshare/testdirectory?restype=directory";
//      Proxy proxy = new Proxy(java.net.Proxy.Type.HTTP,new InetSocketAddress("127.0.0.1", 8888)); 
//      URL serverUrl = new URL(urlString);  
//      HttpURLConnection connection = (HttpURLConnection) serverUrl.openConnection(proxy);
        HttpURLConnection connection = (HttpURLConnection) (new URL(urlString)).openConnection();
        getFileRequest(connection, account, key);
        connection.connect();
        System.out.println("Response message : " + connection.getResponseMessage());
        System.out.println("Response code : " + connection.getResponseCode());

        BufferedReader br = null;
        if (connection.getResponseCode() != 200) {
            br = new BufferedReader(new InputStreamReader((connection.getErrorStream())));
        } else {
            br = new BufferedReader(new InputStreamReader((connection.getInputStream())));
        }
        System.out.println("Response body : " + br.readLine());
    }

    public static void getFileRequest(HttpURLConnection request, String account, String key) throws Exception {
        SimpleDateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss");
        fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = fmt.format(Calendar.getInstance().getTime()) + " GMT";
        String stringToSign = "PUT\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
                + "/" + account + request.getURL().getPath()+"\nrestype:directory"; // resources
        System.out.println("stringToSign : " + stringToSign);
        String auth = getAuthenticationString(stringToSign);
        System.out.println(auth);
        request.setRequestMethod("PUT");
        request.setRequestProperty("x-ms-date", date);
        request.setRequestProperty("x-ms-version", "2015-02-21");
        request.setRequestProperty("Authorization", auth);
        request.setRequestProperty("Content-Length", "0");
    }

    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;
    }

}

Notes:

Please note that System.setProperty("sun.net.http.allowRestrictedHeaders", "true"); in the above code is necessary. I found a parameter called allowRestrictedHeaders from source code , which was originally designed to limit the use of Http Header for security in the design of API.All of the following are limited:

private static final String[] restrictedHeaders = {
    /* Restricted by XMLHttpRequest2 */
    //"Accept-Charset",
    //"Accept-Encoding",
    "Access-Control-Request-Headers",
    "Access-Control-Request-Method",
    "Connection", /* close is allowed */
    "Content-Length",
    //"Cookie",
    //"Cookie2",
    "Content-Transfer-Encoding",
    //"Date",
    "Expect",
    "Host",
    "Keep-Alive",
    "Origin",
    // "Referer", 
    // "TE",
    "Trailer",
    "Transfer-Encoding",
    "Upgrade",
    //"User-Agent",
    "Via"
    };

    allowRestrictedHeaders = ((Boolean)java.security.AccessController.doPrivileged(
        new sun.security.action.GetBooleanAction(
            "sun.net.http.allowRestrictedHeaders"))).booleanValue();

Hope it helps you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM