如何在Java中基于SAS令牌访问Azure WASB容器?

时间:2019-01-30 15:33:20

标签: java azure azure-storage azure-storage-blobs

我正在尝试使用SAS密钥以Java代码从Azure WASB检索容器。这是在HDFS代码中完成的,但是由于任何原因,我似乎都无法使其正常工作。我设法将其简化为下面的应用程序,该应用程序也不起作用。我认为这可能与我们如何生成SAS令牌有关,还是与Azure帐户的权限有关。有人可以看一下这个问题,并向我指出正确的方向吗?谢谢!

{{1}}

1 个答案:

答案 0 :(得分:1)

根据您的代码,我认为您想通过使用SAS为容器构建URL来获取Blob容器的属性和元数据。但是,SharedAccessBlobPolicy生成的SAS字符串类似于blob(sig=1G7tiQnLEtbjk2RSNuUSKH7gLNVZjqhuLQL%2Fci%2FXS50%3D&st=2017-01-30T16%3A00%3A00Z&se=2021-01-30T16%3A00%3A00Z&sv=2018-03-28&sp=racwdl&sr=b)的sr=b,而不是容器(sr=c,例如从Azure存储复制的st=2019-01-31T08%3A38%3A46Z&se=2019-02-01T08%3A38%3A46Z&sp=rl&sv=2018-03-28&sr=c&sig=KnynNYBUtzNSYtBEcYakMrhAXPRIk60wztB3BFv5b%2Bs%3D的{​​{1}}浏览器)。

我尝试通过以下代码将CloudStorageAccountSharedAccessAccountPolicy结合使用,以为斑点生成Account SAS,但仍然无法正常工作。

  

帐户SAS 。帐户SAS委派对一项或多项存储服务中的资源的访问。通过服务SAS可用的所有操作也可以通过帐户SAS进行。此外,使用帐户SAS,您可以委派对适用于给定服务的操作的访问权限,例如“获取/设置服务属性”和“获取服务状态”。您还可以委派对服务SAS不允许的Blob容器,表,队列和文件共享的读取,写入和删除操作的访问权限。有关构建帐户SAS令牌的详细信息,请参阅构建帐户SAS。

SharedAccessAccountPolicy accountPolicy = new SharedAccessAccountPolicy();
accountPolicy.setPermissions(EnumSet.allOf(SharedAccessAccountPermissions.class));
accountPolicy.setSharedAccessStartTime(Date.valueOf(LocalDate.now().minusYears(2)));
accountPolicy.setSharedAccessExpiryTime(Date.valueOf(LocalDate.now().plusYears(2)));

String sas = csa.generateSharedAccessSignature(accountPolicy);

我测试以下代码,

StorageCredentials credentials = new StorageCredentialsSharedAccessSignature(sas);
CloudBlobContainer sasContainer = new CloudBlobContainer(new URI(container2.getUri().toString()+"?"+sas), credentials);
sasContainer.downloadAttributes();

然后获取异常。

Exception in thread "main" java.lang.IllegalArgumentException: Cannot provide credentials as part of the address and as constructor parameter. Either pass in the address or use a different constructor.

或者测试代码CloudBlobContainer sasContainer = new CloudBlobContainer(new URI(container2.getUri().toString()+"?"+sas))以获取异常。

Exception in thread "main" com.microsoft.azure.storage.StorageException: Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.

这似乎是由我在研究SDK源代码后实施Azure Java Storage SDK v8.0.0引起的。也许您可以向Microsoft报告此问题。

我尝试通过以下代码使用Azure Java Storage SDK v10使用SAS生成容器URL,它工作正常。

v10的Maven依赖项:

<!-- https://mvnrepository.com/artifact/com.microsoft.azure/azure-storage-blob -->
<dependency>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>azure-storage-blob</artifactId>
    <version>10.4.0</version>
</dependency>

使用SAS生成容器网址的代码:

String accountName = "<your account name>";
String accountKey = "<your account key>";
SharedKeyCredentials credentials = new SharedKeyCredentials(accountName, accountKey);
final ServiceURL serviceURL = new ServiceURL(new URL("http://" + accountName + ".blob.core.windows.net"), StorageURL.createPipeline(credentials, new PipelineOptions()));
String containerName = "<container name>";
ServiceSASSignatureValues values = new ServiceSASSignatureValues()
                .withProtocol(SASProtocol.HTTPS_ONLY) // Users MUST use HTTPS (not HTTP).
                .withExpiryTime(OffsetDateTime.now().plusDays(2)) // 2 days before expiration.
                .withContainerName(containerName)
                .withBlobName(blobName);
ContainerSASPermission permission = new ContainerSASPermission()
                .withRead(true)
                .withAdd(true)
                .withWrite(true);
values.withPermissions(permission.toString());
SASQueryParameters serviceParams = values.generateSASQueryParameters(credentials);
String sas = serviceParams.encode();

String containerUrlWithSAS = String.format(Locale.ROOT, "https://%s.blob.core.windows.net/%s%s",
                accountName, containerName, sas);
HttpPipeline pipeline = new HttpPipelineBuilder().build();
ContainerURL sasContainer = new ContainerURL(new URL(containerUrlWithSAS), pipeline);
sasContainer.getProperties();

注意:SDK getPropertiesContainerURL的功能v10与SDK downloadAttributesCloudBlobContainer的{​​{1}}相似,该函数也返回容器的元数据和系统属性。