Microsoft states that getting a Blob is just a normal http get https://myaccount.blob.core.windows.net/mycontainer/myblob
. But how do I format the string when I have an account + shared key?
I know there is an Azure SDK, but i'm creating an "add-on" to an existing java ee system, and cannot run in Azure, so I'm using REST Api. This is what i've tried so far:
String account = "myaccount";
String key = "243fedfsdf23f4f";
String protocol = "http";
String storageConnectionString = String.format("DefaultEndpointsProtocol=%s;AccountName=%s;AccountKey=%s", protocol, account, key);
System.out.println(storageConnectionString);
URL url = new URL("https://mysite.azureweb.com/myfile.txt");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
if (conn.getResponseCode() != 200) {
throw new IOException(conn.getResponseMessage());
}
// Buffer the result into a string
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
rd.close();
conn.disconnect();
The string probably needs some Base64 encoding?
Update
The Http request looks like GET https://myAccount.blob.core.windows.net/myDir/myfile.txt HTTP/1.1
x-ms-date: Thu, 01 Oct 2015 12:56:11 GMT
x-ms-version: 2015-02-21
Authorization: SharedKey myAccount:asdfkjsladjfsdf827fhwf298f924f92723dfh23f273f2h7h4f
Host: myAccount.blob.core.windows.net
I "just" need to package this into a request to get a file in /mydir/myfile.txt
There are two access types for Azure Storage. One via Shared Keys and other other one via Shared Access Signatures.
Shared Keys give access to the whole storage account. Per storage account you have two shared keys and they are both equal. Usually you never give your shared keys away. Typically you only use them on the server side not in apps on the client side.
You only want to give someone access to a single file. Therefor using shared keys would be the wrong solution.
Shared Access Signatures give you the possibility to create a (REST) request, that is limited to certain files or containers. You can choose the privileges like write, read, delete etc. And you define a timeframe where the access is valid. For Shared Access Signatures you have two options: a) ad-hoc and b) policy-based. Ad-hoc Shared Access Signatures cannot be easily revoked (you could delete the file or invalidate the shared key which you used to create the Shared Access Signature). Policy-based Shared Access Signatures can easily be revoked by deleting the policy.
If you do not want to use the Azure SDK, you can create your own Shared Access Signatures. How to construct them is explained in the following link:
Constructing a Service SAS
There are also samples.
Service SAS Examples
Your file is stored in a BLOB. So you have to use the service BLOB. On the samples page you find the following BLOB sample.
signedstart=2013-08-16
signedexpiry=2013-08-17
signedresource=c
signedpermissions=r
signature=dD80ihBh5jfNpymO5Hg1IdiJIEvHcJpCMiCMnN/RnbI=
signedidentifier=YWJjZGVmZw==
signedversion=2013-08-15
responsecontent-disposition=file; attachment
responsecontent-type=binary
StringToSign = r + \n
2013-08-16 + \n
2013-08-17 + \n
/myaccount/pictures + \n
YWJjZGVmZw== + \n
2013-08-15 + \n
+ \n
file; attachment + \n
+ \n
+ \n
binary
HMAC-SHA256(URL.Decode(UTF8.Encode(StringToSign))) = a39+YozJhGp6miujGymjRpN8tsrQfLo9Z3i8IRyIpnQ=
Finally you get a URL for your REST request.
GET https://myaccount.blob.core.windows.net/pictures/profile.jpg?sv=2013-08-15&st=2013-08-16&se=2013-08-17&sr=c&sp=r&rscd=file;%20attachment&rsct=binary &sig=YWJjZGVmZw%3d%3d&sig=a39%2BYozJhGp6miujGymjRpN8tsrQfLo9Z3i8IRyIpnQ%3d HTTP/1.1
Have a look on the two pages for the full explanation.
There is a simple way to generate the SAS for getting files in the private container by using the Azure Storage SDK.
Following the sample code below to generat the SAS key and format the URL:
String accountName = "<your_account_name>";
String accountKey = "<your_account_key>";
String containerName = "<your_private_container_name>";
String blobFileName = "<your_blob_file_name>";
String storageConnectionString = String.format("DefaultEndpointsProtocol=%s;AccountName=%s;AccountKey=%s", "https", accountName, accountKey);
CloudStorageAccount account = CloudStorageAccount.parse(storageConnectionString);
CloudBlobClient blobClient = account.createCloudBlobClient();
CloudBlobContainer container = blobClient.getContainerReference(containerName);
CloudBlockBlob blob = container.getBlockBlobReference(blobFileName);
SharedAccessBlobPolicy policy = new SharedAccessBlobPolicy();
GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
calendar.setTime(new Date());
policy.setSharedAccessStartTime(calendar.getTime());
calendar.add(Calendar.HOUR, 1);
policy.setSharedAccessExpiryTime(calendar.getTime());
policy.setPermissions(EnumSet.of(SharedAccessBlobPermissions.READ));
String sas = blob.generateSharedAccessSignature(policy, null);
System.out.println(sas)
String urlstr = String.format("https://%s.blob.core.windows.net/%s/%s?%s", accountName, containerName, blobFileName, sas);
System.out.println(urlstr);
For details, you can refer to the doc https://msdn.microsoft.com/en-us/library/hh875756.aspx.