我有一个blob容器,其ACL设置为允许完全公开读取访问权限,因此任何人都可以读取并列出该容器中的blob。
我存储文件,以便客户端使用的WPF客户端应用程序可以读取它们,但我不想让它们修改/删除/创建文件。
有谁知道在这种情况下应该使用什么连接字符串?
我希望指定没有帐户密钥和/或共享访问密钥的连接字符串,因为blob是公共的但不起作用 - StorageAccount.Parse抛出FormatException
答案 0 :(得分:1)
据我所知,StorageAccount并不意味着连接到公共blob。您只需使用WebClient或其他可以通过公共http / https端点下载数据的工具,通过公共URL访问公共blob。
答案 1 :(得分:1)
如前面的答案所述,最佳做法通常是使用共享访问签名(SAS)或存储的访问策略来控制对blob容器的访问。这些可用于创建您可以传递给客户的访问令牌(字符串),而不会泄露您的帐户密钥。
但是,也可以指定对blob的公共读取访问级别以及容器中保存的元数据。对于拥有容器或blob的公共访问URL的匿名用户,公共访问是自动读取权限级别。您无法使用公共访问权限授予匿名用户对容器的写入权限。如果您需要向不具有Azure存储帐户的帐户密钥的用户授予写入权限,则需要以URL的形式向这些用户提供引用共享访问签名或共享的令牌访问政策。 如果对blob容器的公共访问权限当前不是(私有),则匿名用户将能够使用公共访问URL(如下所示)读取容器中的所有blob。
http://grassy.blob.core.windows.net/container1/image2.jpg
创建容器时,可以将publicAccess属性的值设置为BlobContainerPublicAccessType枚举的相应常量。 publicAccess属性的值可以是以下三个常量之一,它们指定公共读取访问的级别。
•BLOB - 公众可以读取此容器中blob的内容和元数据,但无法读取容器元数据或列出容器中的blob。
•容器 - 公众可以读取blob内容和元数据以及容器元数据,并可以列出容器中的blob。
•OFF - 指定无公共访问权限。只有帐户所有者才能读取此容器中的资源。
因此,在这种情况下,公共访问级别可能设置为CONTAINER。例如:
public static void main(String[] args) throws InvalidKeyException, URISyntaxException, StorageException
{
Account creds = new Account();
final String storageConnectionString = creds.getstorageconnectionstring();
CloudStorageAccount storageAccount = CloudStorageAccount.parse(storageConnectionString);
CloudBlobClient blobClient = storageAccount.createCloudBlobClient();
CloudBlobContainer container = blobClient.getContainerReference("container1");
container.createIfNotExist();
BlobContainerPermissions containerPermissions = new BlobContainerPermissions();
containerPermissions.setPublicAccess(BlobContainerPublicAccessType.CONTAINER);
container.uploadPermissions(containerPermissions);
BlobContainerPublicAccessType access1 = containerPermissions.getPublicAccess();
System.out.println("Public access to " + container.getName() + " is set to:
" + access1);
}
如果container1上的公共访问级别已设置为CONTAINER,则匿名用户应该能够在container1中列出blob,只知道存储帐户AccountName(“grassy”)和容器名称,但无需知道AccountKey。例如,匿名应用程序可能使用类似于以下内容的Java代码:
public static void main(String[] args) throws InvalidKeyException, URISyntaxException, StorageException, FileNotFoundException, IOException
{
URI baseuri = new URI("http://grassy.blob.core.windows.net");
CloudBlobClient blobclient = new CloudBlobClient(baseuri);
CloudBlobContainer container = blobclient.getContainerReference("container1");
for (ListBlobItem blobItem : container.listBlobs()){System.out.println(blobItem.getUri());}
}
但是,正如所讨论的,避免让匿名用户访问是一种更好的做法。而是使用SAS或策略控制对容器的访问,并将令牌传递给仅已知用户。
答案 2 :(得分:0)
您可以为此目的使用共享访问签名。您可以做的是在blob容器上创建SAS,该容器仅允许blob容器上的列表和读取权限,然后将该SAS URI分发给您的客户端。然后,您的代码可以使用该SAS URI创建BlobContainer
对象的实例。
以下是使用SAS URI列出Blob容器中blob的示例代码:
static void ListBlobsWithStorageClientLibrary(string blobContainerSasUri)
{
CloudBlobContainer blobContainer = new CloudBlobContainer(new Uri(blobContainerSasUri));
var blobs = blobContainer.ListBlobs(null, true);
foreach (var blob in blobs)
{
Console.WriteLine(blob.Uri);
}
}
其他替代方法是使用SAS令牌创建StorageCredentials
对象的实例:http://msdn.microsoft.com/en-us/library/windowsazure/jj682529.aspx。然后,您可以使用StorageCredentials对象创建CloudStorageAccount
对象的实例。
我写了一篇关于使用带有blob存储的共享访问签名的详细帖子,您可以在此处阅读:http://gauravmantri.com/2013/02/13/revisiting-windows-azure-shared-access-signature/