简体   繁体   English

无法通过Rest API访问Azure Blob

[英]Cannot access azure blobs through rest api

I was able to create a Container in Storage Account and upload a blob to it through the Client Side Code. 我能够在存储帐户中创建一个容器,然后通过客户端代码将一个Blob上载到该容器。

I was able to make the blob available for Public access as well , such that when I hit the following query from my browser, I am able to see the image which I uploaded. 我也可以使该Blob可供“公共访问”使用,这样,当我从浏览器中命中以下查询时,便可以看到上传的图像。

https://MYACCOUNT.blob.core.windows.net/MYCONTAINER/MYBLOB

I now have a requirement to use the rest service to retrieve the contents of the blob. 现在,我需要使用rest服务来检索blob的内容。 I wrote down the following java code. 我写下了以下Java代码。

package main;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class GetBlob {


public static void main(String[] args) {





    String url="https://MYACCOUNT.blob.core.windows.net/MYCONTAINER/MYBLOB";


    try {
        System.out.println("RUNNIGN");
    HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();


 connection.setRequestProperty("Authorization", createQuery());
 connection.setRequestProperty("x-ms-version", "2009-09-19");

        InputStream response = connection.getInputStream();
        System.out.println("SUCCESSS");
        String line;
        BufferedReader reader = new BufferedReader(new InputStreamReader(response));
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }   



    } catch (IOException e) {
        e.printStackTrace();
    }

}
public static String createQuery()
{
    String dateFormat="EEE, dd MMM yyyy hh:mm:ss zzz";
    SimpleDateFormat dateFormatGmt = new SimpleDateFormat(dateFormat);
    dateFormatGmt.setTimeZone(TimeZone.getTimeZone("UTC"));
    String date=dateFormatGmt.format(new Date());


    String Signature="GET\n\n\n\n\n\n\n\n\n\n\n\n" +
            "x-ms-date:" +date+
            "\nx-ms-version:2009-09-19" ;

            // I do not know CANOCALIZED RESOURCE 
            //WHAT ARE THEY??
//          +"\n/myaccount/myaccount/mycontainer\ncomp:metadata\nrestype:container\ntimeout:20";

    String SharedKey="SharedKey";
    String AccountName="MYACCOUNT";

    String encryptedSignature=(encrypt(Signature));

    String auth=""+SharedKey+" "+AccountName+":"+encryptedSignature;

        return auth;

}





public static String encrypt(String clearTextPassword)   {  
    try {
      MessageDigest md = MessageDigest.getInstance("SHA-256");
      md.update(clearTextPassword.getBytes());
      return new sun.misc.BASE64Encoder().encode(md.digest());
    } catch (NoSuchAlgorithmException e) {
    }
    return "";
  }



}

However , I get the following error when I run this main class... 但是,运行此主类时出现以下错误...

RUNNIGN
java.io.IOException: Server returned HTTP response code: 403 for URL:     https://klabs.blob.core.windows.net/delete/Blob_1
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
at main.MainClass.main(MainClass.java:61)

Question1: Why this error, did I miss any header/parameter? 问题1:为什么会出现此错误,我是否错过任何标题/参数?

Question2: Do I need to add headers in the first place, because I am able to hit the request from the browser without any issues. Question2:我是否需要首先添加标题,因为我能够从浏览器中访问请求而没有任何问题。

Question3: Can it be an SSL issue? 问题3:这可能是SSL问题吗? What is the concept of certificates, and how and where to add them? 证书的概念是什么,以及如何以及在何处添加证书? Do I really need them? 我真的需要它们吗? Will I need them later, when I do bigger operations on my blob storage(I want to manage a thousand blobs)? 当我在Blob存储上执行较大的操作(我想管理一千个Blob)时,以后是否需要它们?

Will be thankful for any reference as well, within Azure and otherwise that could help me understand better. 还要感谢Azure中的任何参考,否则可以帮助我更好地理解。 :D :d



AFTER A FEW DAYS 几天后



Below is my new code for PutBlob I azure. 以下是天蓝色的PutBlob的新代码。 I believe I have fully resolved all header and parameter issues and my request is perfect. 我相信我已经完全解决了所有标头和参数问题,并且我的要求很完美。 However I am still getting the same 403. I do not know what the issue is. 但是我仍然收到相同的403。我不知道问题出在哪里。 Azure is proving to be pretty difficult. 事实证明,Azure很难。

A thing to note is that the containers name is delete, and I want to create a blob inside it, say newBlob. 需要注意的是容器名称是delete,我想在其中创建一个blob,例如newBlob。 I tried to initialize the urlPath in the code below with both "delete" and "delete/newBlob". 我试图在下面的代码中使用“ delete”和“ delete / newBlob”来初始化urlPath。 Does not work.. 不起作用..

package main;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;

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

import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
import com.sun.org.apache.xml.internal.security.utils.Base64;

public class Internet {

    static String key="password";
    static String account="klabs";
private static Base64 base64 ; 
private static String createAuthorizationHeader(String canonicalizedString) throws InvalidKeyException, Base64DecodingException, NoSuchAlgorithmException, IllegalStateException, UnsupportedEncodingException     {  
          Mac mac = Mac.getInstance("HmacSHA256");  
          mac.init(new SecretKeySpec(base64.decode(key), "HmacSHA256"));  
          String authKey = new String(base64.encode(mac.doFinal(canonicalizedString.getBytes("UTF-8"))));  
          String authStr = "SharedKey " + account + ":" + authKey;  
          return authStr;  
     } 

public static void main(String[] args) {

System.out.println("INTERNET");
String key="password";
String account="klabs";
long blobLength="Dipanshu Verma wrote this".getBytes().length;
File f = new File("C:\\Users\\Dipanshu\\Desktop\\abc.txt");
String requestMethod = "PUT";  
String urlPath = "delete";
String storageServiceVersion = "2009-09-19";


SimpleDateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:sss");  
fmt.setTimeZone(TimeZone.getTimeZone("UTC"));  
String date = fmt.format(Calendar.getInstance().getTime()) + " UTC";
String blobType = "BlockBlob"; 
String canonicalizedHeaders = "x-ms-blob-type:"+blobType+"\nx-ms-date:"+date+"\nx-ms-version:"+storageServiceVersion;  
String canonicalizedResource = "/"+account+"/"+urlPath;  

String stringToSign = requestMethod+"\n\n\n"+blobLength+"\n\n\n\n\n\n\n\n\n"+canonicalizedHeaders+"\n"+canonicalizedResource;

try {
    String authorizationHeader = createAuthorizationHeader(stringToSign);
    URL myUrl = new URL("https://klabs.blob.core.windows.net/" + urlPath);

    HttpURLConnection connection=(HttpURLConnection)myUrl.openConnection();
    connection.setRequestProperty("x-ms-blob-type", blobType);
    connection.setRequestProperty("Content-Length", String.valueOf(blobLength));
    connection.setRequestProperty("x-ms-date", date);
    connection.setRequestProperty("x-ms-version", storageServiceVersion);
    connection.setRequestProperty("Authorization", authorizationHeader);
    connection.setDoOutput(true);
    connection.setRequestMethod("POST");
    System.out.println(String.valueOf(blobLength));
    System.out.println(date);
    System.out.println(storageServiceVersion);
    System.out.println(stringToSign);
    System.out.println(authorizationHeader);
    System.out.println(connection.getDoOutput());


    DataOutputStream  outStream = new DataOutputStream(connection.getOutputStream());


       // Send request
       outStream.writeBytes("Dipanshu Verma wrote this");
       outStream.flush();
       outStream.close();
       DataInputStream inStream = new DataInputStream(connection.getInputStream());
       System.out.println("BULLA");

       String buffer;
       while((buffer = inStream.readLine()) != null) {
           System.out.println(buffer);
       }

       // Close I/O streams
       inStream.close();
       outStream.close();





} catch (InvalidKeyException | Base64DecodingException | NoSuchAlgorithmException | IllegalStateException | UnsupportedEncodingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
}

}

I know only a proper code reviewer might be able to help me, please do it if you can. 我知道只有适当的代码审阅者才能为我提供帮助,如果可以的话,请这样做。 Thanks 谢谢

Question1: Why this error, did I miss any header/parameter? 问题1:为什么会出现此错误,我是否错过任何标题/参数?

Most likely you're getting this error is because of incorrect signature. 您最有可能收到此错误是由于签名不正确。 Please refer to MSDN documentation for creating correct signature: http://msdn.microsoft.com/en-us/library/azure/dd179428.aspx . 请参考MSDN文档以创建正确的签名: http : //msdn.microsoft.com/zh-cn/library/azure/dd179428.aspx Unless your signature is correct you'll not be able to perform operations using REST API. 除非您的签名正确,否则您将无法使用REST API执行操作。

Question2: Do I need to add headers in the first place, because I am able to hit the request from the browser without any issues. Question2:我是否需要首先添加标题,因为我能够从浏览器中访问请求而没有任何问题。

In your current scenario, because you can access the blob directly (which in turn means the container in which the blob exist has Public or Blob ACL) you don't really need to use REST API. 在当前情况下,由于您可以直接访问Blob(这反过来意味着Blob存在的容器具有PublicBlob ACL),因此您实际上不需要使用REST API。 You can simply make a HTTP request using Java and read the response stream which will have blob contents. 您可以简单地使用Java发出HTTP请求并读取包含blob内容的响应流。 You would need to go down this route if the container ACL is Private because in this case your requests need to be authenticated and the code above creates an authenticated request. 如果容器ACL为“ Private则您需要沿着这条路线走,因为在这种情况下,您的请求需要进行身份验证,并且上面的代码创建了经过身份验证的请求。

Question3: Can it be an SSL issue? 问题3:这可能是SSL问题吗? What is the concept of certificates, and how and where to add them? 证书的概念是什么,以及如何以及在何处添加证书? Do I really need them? 我真的需要它们吗? Will I need them later, when I do bigger operations on my blob storage(I want to manage a thousand blobs)? 当我在Blob存储上执行较大的操作(我想管理一千个Blob)时,以后是否需要它们?

No, it is not an SSL issue. 不,这不是SSL问题。 Its an issue with incorrect signature. 这是签名错误的问题。

Finally found the mistake!! 终于发现了错误!!

In the code above , I was using a String "password" as key for my SHA2 在上面的代码中,我使用String“ password”作为我的SHA2的键

base64.decode(key)

It should have been the key associated with my account with AZURE. 它应该是与我的AZURE帐户关联的密钥。 Silly One!! 傻一! Took me 2 weeks to find. 花了我两个星期的时间找到。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 用于块Blob的Azure存储服务REST API:内容长度问题 - Azure Storage service REST API for block Blobs : Content Length Issue 通过REST API在Azure中删除用户的经理 - Delete user's manager in Azure through REST api 如何通过邮递员调用REST API在Azure中创建索引? - How to call REST API through postman to create index in Azure? 如何通过REST API java在Azure DevOps中添加测试结果? - How to add test results in Azure DevOps through REST API java? 使用Java在Azure中访问Office 365(SharePoint REST API) - Access Office 365 (sharepoint REST api) in Azure using Java 如何使用REST API(ARM)访问Azure存储表 - How to access Azure Storage Table using REST API (ARM) 使用Rest API在Azure IoT中心中创建共享访问策略 - Shared Access Policy Creation in Azure IoT Hub using Rest API 如何通过Rest api或Java SDK停止Azure VM以来的时间 - How to get the time since when my Azure VM is stopped through Rest api or Java sdk 使用 azure devops 的 rest api - Using rest api of azure devops 尝试通过 REST API 访问 Azure 数据湖存储 Gen 2 中的文件系统时出现 403 错误 - 403 error when trying to access file system in Azure data lake storage Gen 2 via REST API
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM