繁体   English   中英

无法通过Rest API访问Azure Blob

[英]Cannot access azure blobs through rest api

我能够在存储帐户中创建一个容器,然后通过客户端代码将一个Blob上载到该容器。

我也可以使该Blob可供“公共访问”使用,这样,当我从浏览器中命中以下查询时,便可以看到上传的图像。

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

现在,我需要使用rest服务来检索blob的内容。 我写下了以下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 "";
  }



}

但是,运行此主类时出现以下错误...

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)

问题1:为什么会出现此错误,我是否错过任何标题/参数?

Question2:我是否需要首先添加标题,因为我能够从浏览器中访问请求而没有任何问题。

问题3:这可能是SSL问题吗? 证书的概念是什么,以及如何以及在何处添加证书? 我真的需要它们吗? 当我在Blob存储上执行较大的操作(我想管理一千个Blob)时,以后是否需要它们?

还要感谢Azure中的任何参考,否则可以帮助我更好地理解。 :d



几天后



以下是天蓝色的PutBlob的新代码。 我相信我已经完全解决了所有标头和参数问题,并且我的要求很完美。 但是我仍然收到相同的403。我不知道问题出在哪里。 事实证明,Azure很难。

需要注意的是容器名称是delete,我想在其中创建一个blob,例如newBlob。 我试图在下面的代码中使用“ delete”和“ delete / newBlob”来初始化urlPath。 不起作用..

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

}

我知道只有适当的代码审阅者才能为我提供帮助,如果可以的话,请这样做。 谢谢

问题1:为什么会出现此错误,我是否错过任何标题/参数?

您最有可能收到此错误是由于签名不正确。 请参考MSDN文档以创建正确的签名: http : //msdn.microsoft.com/zh-cn/library/azure/dd179428.aspx 除非您的签名正确,否则您将无法使用REST API执行操作。

Question2:我是否需要首先添加标题,因为我能够从浏览器中访问请求而没有任何问题。

在当前情况下,由于您可以直接访问Blob(这反过来意味着Blob存在的容器具有PublicBlob ACL),因此您实际上不需要使用REST API。 您可以简单地使用Java发出HTTP请求并读取包含blob内容的响应流。 如果容器ACL为“ Private则您需要沿着这条路线走,因为在这种情况下,您的请求需要进行身份验证,并且上面的代码创建了经过身份验证的请求。

问题3:这可能是SSL问题吗? 证书的概念是什么,以及如何以及在何处添加证书? 我真的需要它们吗? 当我在Blob存储上执行较大的操作(我想管理一千个Blob)时,以后是否需要它们?

不,这不是SSL问题。 这是签名错误的问题。

终于发现了错误!!

在上面的代码中,我使用String“ password”作为我的SHA2的键

base64.decode(key)

它应该是与我的AZURE帐户关联的密钥。 傻一! 花了我两个星期的时间找到。

暂无
暂无

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

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