Azure Blob存储:使用共享密钥身份验证的快照Blob

Azure Blob存储:使用共享密钥身份验证的快照Blob,azure,azure-storage-blobs,Azure,Azure Storage Blobs,我正在使用下面提到的微软的快照RESTAPI 我生成的授权共享密钥非常适合于所有其他具有GET REST API调用的操作,如GetBlob、ListContainer、ListBlob 我认为对于POST调用,我得到了错误,但生成授权共享密钥的逻辑是相同的 Cannonical资源/storageaccountname/containername/8447a36f-43a3-4927-a23f-b8839f4c55e3DataDisk.vhd 组件:快照 Cannonical Header

我正在使用下面提到的微软的快照RESTAPI

我生成的授权共享密钥非常适合于所有其他具有GET REST API调用的操作,如GetBlob、ListContainer、ListBlob

我认为对于POST调用,我得到了错误,但生成授权共享密钥的逻辑是相同的

Cannonical资源/storageaccountname/containername/8447a36f-43a3-4927-a23f-b8839f4c55e3DataDisk.vhd 组件:快照

Cannonical Header:x-ms-date:Thu,2017年5月18日09:42:05 GMT x-ms-version:2014-02-14

获取以下提到的错误:

身份验证失败 服务器无法对请求进行身份验证。确保包括签名在内的授权标头的值格式正确。请求ID:70447bc6-0001-0043-4271-d05281000000时间:2017-05-19T07:27:25.2321062Z 在HTTP请求“7ffeyc4sufwh5oh1dlg7qx1zrceffesddwmgkqwzyo=”中找到的MAC签名与任何计算签名不同。服务器使用以下字符串进行签名:“放置0 x-ms-date:Fri,2017年5月19日07:26:46 GMT x-ms-version:2014-02-14/CSAgilitySouthCentralus/vhds/8447a36f-43a3-4927-a23f-b8839f4c55e3AgilityDataDisk.vhd组件:快照”。

在标题中告诉我我需要设置任何其他必需参数,如内容长度、内容类型等

网址:

标题: 授权:SharedKey storgeaccountname:gHYtJ5uOEQNztcdTpqAr3E20cARyFnrV8b3zuDpO9uk=

x-ms-version:2014-02-14 x-ms-date:2017年5月17日星期三格林威治标准时间10:01:47

用于直接生成授权SharedKey的Java代码我们可以创建类并复制粘贴此代码:

publicstaticvoidmain(String…arg)抛出URISyntaxException,Exception{

     Map<String, String> requestHeaders = new HashMap<>();
     requestHeaders.put("x-ms-version", "2014-02-14");
     requestHeaders.put("x-ms-date", getStorageDate());


    getAuthorizationHeader("PUT","storageaccount","storagekey",new URI("https://storageaccount.blob.core.windows.net/vhds/8447a36f-43a3-4927-a23f-b8839f4c55e3.vhd?comp=snapshot"),requestHeaders);
}

  public static String getStorageDate()
    {
        Date d = new Date(System.currentTimeMillis());
        SimpleDateFormat f = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
        f.setTimeZone(TimeZone.getTimeZone("GMT"));
        String dateString = f.format(d);
        return dateString;
    }


  public static String getAuthorizationHeader(String verb, String storageAccount, String storageKey, URI resourceURI,
          Map<String, String> requestHeaders) throws Exception
    {
        String authorizationStringToHash = getAuthorizationStringToHash(verb, storageAccount, requestHeaders, resourceURI);
        String authorizationHash = hashString(storageKey, authorizationStringToHash);
        System.out.println("StorageAccoutName::" + storageAccount);
        System.out.println("Storage Key::" + storageKey);
        System.out.println("authorizationStringToHash::" + authorizationStringToHash);
        System.out.println("authorizationHash:: " + authorizationHash);
      /*  System.out.println(HttpClientFactory.getInstance()
                .createHeader("Authorization", "SharedKey " + storageAccount + ":" + authorizationHash).getValue());*/
       System.out.println("Authorization SharedKey " + storageAccount + ":" + authorizationHash);
       return "";
    }

    public static String getAuthorizationStringToHash(String verb, String storageAccount,  Map<String, String> headers,
            URI resourceURI) throws Exception
    {

        Map<String, String> headersToCanonicalize = new HashMap<String, String>();

        String contentEncoding = "";
        String contentLanguage = "";
        String contentLength = "";
        String contentMD5 = "";
        String contentType = "";
        String date = "";
        String ifModifiedSince = "";
        String ifMatch = "";
        String ifNoneMatch = "";
        String ifUnModifiedSince = "";
        String range = "";
        Set<String> keySet = headers.keySet();
        for (String header : keySet)
        {
            if ("content-encoding".equals(header))
            {
                contentEncoding = headers.get(header);
            }
            else if ("content-language".equals(header))
            {
                contentLanguage = headers.get(header);
            }
            else if ("content-length".equals(header))
            {
                contentLength = headers.get(header);
            }
            else if ("content-md5".equals(header))
            {
                contentType = headers.get(header);
            }
            else if ("content-type".equals(header))
            {
                contentType = headers.get(header);
            }
            else if ("date".equals(header))
            {
                date = "";
            }
            else if ("if-modified-since".equals(header))
            {
                ifModifiedSince =headers.get(header);
            }
            else if ("if-match".equals(header))
            {
                ifMatch = headers.get(header);
            }
            else if ("if-none-match".equals(header))
            {
                ifNoneMatch =headers.get(header);
            }
            else if ("if-unmodified-since".equals(header))
            {
                ifUnModifiedSince =headers.get(header);
            }
            else if ("range".equals(header))
            {
                range = headers.get(header);
            }
            else
            {
                headersToCanonicalize.put(header, headers.get(header));
            }
        }

        StringBuffer hashBuffer = new StringBuffer(verb);
        hashBuffer.append("\n");
        hashBuffer.append(contentEncoding);
        hashBuffer.append("\n");
        hashBuffer.append(contentLanguage);
        hashBuffer.append("\n");
        hashBuffer.append(contentLength);
        hashBuffer.append("\n");
        hashBuffer.append(contentMD5);
        hashBuffer.append("\n");
        hashBuffer.append(contentType);
        hashBuffer.append("\n");
        hashBuffer.append(date);
        hashBuffer.append("\n");
        hashBuffer.append(ifModifiedSince);
        hashBuffer.append("\n");
        hashBuffer.append(ifMatch);
        hashBuffer.append("\n");
        hashBuffer.append(ifNoneMatch);
        hashBuffer.append("\n");
        hashBuffer.append(ifUnModifiedSince);
        hashBuffer.append("\n");
        hashBuffer.append(range);
        hashBuffer.append("\n");

        List<String> headerNames = new ArrayList<String>(headersToCanonicalize.keySet());
        Collections.sort(headerNames);
        for (String headerName : headerNames)
        {
            hashBuffer.append(canonicalizeHeader(headerName,headersToCanonicalize.get(headerName)));
            hashBuffer.append("\n");
        }

        hashBuffer.append(canonicalizeResource(storageAccount, resourceURI.getPath(), resourceURI.getQuery()));

        return hashBuffer.toString();
    }

    public static String hashString(String key, String stringToHash) throws Exception
    {
        byte[] keyBytes = DatatypeConverter.parseBase64Binary(key);

        SecretKey myKey = new SecretKeySpec(keyBytes, "HMACSHA256");
        Mac mac = Mac.getInstance("HMACSHA256");
        mac.init(myKey);

        byte[] stringUTF8Bytes = stringToHash.getBytes("UTF-8");
        byte[] macBytes = mac.doFinal(stringUTF8Bytes);

        return DatatypeConverter.printBase64Binary(macBytes);
    }

    public static String canonicalizeHeader(String headerName,String headervalue)
    {
        return headerName + ":" + headervalue;
    }

    // uri must not start with /
    public static String canonicalizeResource(String account, String resourcePath, String query)
    {
        StringBuffer canonicalResourceBuffer = new StringBuffer("/");
        canonicalResourceBuffer.append(account);
        canonicalResourceBuffer.append(resourcePath);
        List<String> sortedQueryParams = getOrderedQueryParams(query);
        for (String queryParam : sortedQueryParams)
        {
            canonicalResourceBuffer.append("\n");
            canonicalResourceBuffer.append(queryParam);
        }
        System.out.println("Cannonical Resource "+canonicalResourceBuffer.toString());
        return canonicalResourceBuffer.toString();
    }

    public static List<String> getOrderedQueryParams(String queryParamsString)
    {
        Map<String, String> queryParams = new HashMap<String, String>();
        if ((queryParamsString == null) || (queryParamsString.isEmpty()))
        {
            return Collections.EMPTY_LIST;
        }

        String[] queryParamsArray = queryParamsString.split("&");
        if ((queryParamsArray == null) || (queryParamsArray.length == 0))
        {
            return Collections.EMPTY_LIST;
        }

        Arrays.sort(queryParamsArray);

        for (String queryParam : queryParamsArray)
        {
            queryParam = queryParam.trim();
            queryParam = queryParam.replaceFirst("[ \t]*=[ \t]*", "=");
            String[] parts = queryParam.split("=");
            if (parts.length == 2)
            {
                String key = parts[0];
                String value = parts[1];
                String currentValue = queryParams.get(key);
                if (currentValue == null)
                {
                    queryParams.put(key, value);
                }
                else
                {
                    queryParams.put(key, currentValue + "," + value);
                }
            }
        }

        List<String> names = new ArrayList(queryParams.keySet());
        Collections.sort(names);
        List<String> sortedCanonicalQueryParams = new ArrayList<String>();
        for (String name : names)
        {
            sortedCanonicalQueryParams.add(name + ":" + queryParams.get(name));
        }
        return sortedCanonicalQueryParams;
    }
Map requestHeaders=new HashMap();
requestHeaders.put(“x-ms-version”、“2014-02-14”);
put(“x-ms-date”,getStorageDate());
getAuthorizationHeader(“PUT”、“storageaccount”、“storagekey”),新URI(“https://storageaccount.blob.core.windows.net/vhds/8447a36f-43a3-4927-a23f-b8839f4c55e3.vhd?comp=snapshot)、请求头);
}
公共静态字符串getStorageDate()
{
日期d=新日期(System.currentTimeMillis());
SimpleDataFormat f=新的SimpleDataFormat(“EEE,dd MMM yyyy HH:mm:ss zzz”);
f、 设置时区(TimeZone.getTimeZone(“GMT”);
字符串dateString=f.format(d);
返回日期字符串;
}
公共静态字符串getAuthorizationHeader(字符串动词、字符串storageAccount、字符串storageKey、URI resourceURI、,
MapRequestHeaders)引发异常
{
String authorizationStringToHash=getAuthorizationStringToHash(动词、storageAccount、requestHeaders、resourceURI);
String authorizationHash=hashString(storageKey,authorizationStringToHash);
System.out.println(“StorageAccountName::”+storageAccount);
System.out.println(“存储键::”+storageKey);
System.out.println(“authorizationStringToHash::”+authorizationStringToHash);
System.out.println(“authorizationHash::”+authorizationHash);
/*System.out.println(HttpClientFactory.getInstance()
.createHeader(“授权”、“SharedKey”+storageAccount+:“+authorizationHash).getValue())*/
System.out.println(“授权共享密钥”+storageAccount+:“+authorizationHash”);
返回“”;
}
公共静态字符串getAuthorizationStringToHash(字符串谓词、字符串存储帐户、映射头、,
URI(resourceURI)引发异常
{
Map headersToCanonicalize=new HashMap();
字符串contentEncoding=“”;
字符串contentLanguage=“”;
字符串contentLength=“”;
字符串contentMD5=“”;
字符串contentType=“”;
字符串日期=”;
字符串ifModifiedSince=“”;
字符串ifMatch=“”;
字符串ifNoneMatch=“”;
字符串ifUnModifiedSince=“”;
字符串范围=”;
Set keySet=headers.keySet();
for(字符串头:键集)
{
if(“内容编码”。等于(标题))
{
contentEncoding=headers.get(header);
}
else if(“内容语言”.equals(标题))
{
contentLanguage=headers.get(header);
}
else if(“内容长度”。等于(标题))
{
contentLength=headers.get(header);
}
else if(“content-md5.”等于(标题))
{
contentType=headers.get(header);
}
else if(“内容类型”。等于(标题))
{
contentType=headers.get(header);
}
否则,如果(“日期”。等于(标题))
{
日期=”;
}
else if(“if-modified-since.”等于(标题))
{
ifModifiedSince=headers.get(header);
}
else if(“if match.”等于(标题))
{
ifMatch=headers.get(header);
}
else if(“if none match.”等于(标题))
{
ifNoneMatch=headers.get(header);
}
else if(“如果未修改自“.equals(header))
{
ifUnModifiedSince=headers.get(header);
}
否则,如果(“范围”。等于(标题))
{
范围=标题。获取(标题);
}
其他的
{
headersToCanonicalize.put(header,headers.get(header));
}
}
StringBuffer hashBuffer=新的StringBuffer(动词);
hashBuffer.append(“\n”);
append(contentEncoding);
hashBuffer.append(“\n”);
append(contentLanguage);
hashBuffer.append(“\n”);
append(contentLength);
hashBuffer.append(“\n”);
append(contentMD5);